Rollup merge of #111997 - GuillaumeGomez:re-export-doc-hidden-macros, r=notriddle
Fix re-export of doc hidden macro not showing up
It's part of the follow-up of https://github.com/rust-lang/rust/pull/109697.
Re-exports of doc hidden macros should be visible. It was the only kind of re-export of doc hidden item that didn't show up.
r? `@notriddle`
diff --git a/Cargo.lock b/Cargo.lock
index d584051..efd3d85 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -726,9 +726,9 @@
[[package]]
name = "compiler_builtins"
-version = "0.1.91"
+version = "0.1.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
+checksum = "64518f1ae689f74db058bbfb3238dfe6eb53f59f4ae712f1ff4348628522e190"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -2779,9 +2779,9 @@
[[package]]
name = "pulldown-cmark"
-version = "0.9.2"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
+checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
dependencies = [
"bitflags",
"memchr",
@@ -4380,6 +4380,15 @@
]
[[package]]
+name = "rustdoc-gui-test"
+version = "0.1.0"
+dependencies = [
+ "compiletest",
+ "getopts",
+ "walkdir",
+]
+
+[[package]]
name = "rustdoc-json-types"
version = "0.1.0"
dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
index 53331e2..8eb378a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -40,6 +40,7 @@
"src/tools/generate-copyright",
"src/tools/suggest-tests",
"src/tools/generate-windows-sys",
+ "src/tools/rustdoc-gui-test",
]
exclude = [
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 43b429f..4360fbe 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2391,10 +2391,10 @@
impl FnDecl {
pub fn has_self(&self) -> bool {
- self.inputs.get(0).map_or(false, Param::is_self)
+ self.inputs.get(0).is_some_and(Param::is_self)
}
pub fn c_variadic(&self) -> bool {
- self.inputs.last().map_or(false, |arg| matches!(arg.ty.kind, TyKind::CVarArgs))
+ self.inputs.last().is_some_and(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
}
}
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index e6c4db9..15fe295 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -149,7 +149,7 @@
}
pub fn may_have_doc_links(&self) -> bool {
- self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
+ self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
}
pub fn is_proc_macro_attr(&self) -> bool {
@@ -441,12 +441,12 @@
/// Returns `true` if this list item is a MetaItem with a name of `name`.
pub fn has_name(&self, name: Symbol) -> bool {
- self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
+ self.meta_item().is_some_and(|meta_item| meta_item.has_name(name))
}
/// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
pub fn is_word(&self) -> bool {
- self.meta_item().map_or(false, |meta_item| meta_item.is_word())
+ self.meta_item().is_some_and(|meta_item| meta_item.is_word())
}
/// Gets a list of inner meta items from a list `MetaItem` type.
diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs
index 3593949..e87f6e8 100644
--- a/compiler/rustc_ast/src/expand/allocator.rs
+++ b/compiler/rustc_ast/src/expand/allocator.rs
@@ -1,20 +1,28 @@
use rustc_span::symbol::{sym, Symbol};
-#[derive(Clone, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)]
pub enum AllocatorKind {
Global,
Default,
}
-impl AllocatorKind {
- pub fn fn_name(&self, base: Symbol) -> String {
- match *self {
- AllocatorKind::Global => format!("__rg_{base}"),
- AllocatorKind::Default => format!("__rdl_{base}"),
- }
+pub fn global_fn_name(base: Symbol) -> String {
+ format!("__rust_{base}")
+}
+
+pub fn default_fn_name(base: Symbol) -> String {
+ format!("__rdl_{base}")
+}
+
+pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str {
+ match alloc_error_handler_kind {
+ AllocatorKind::Global => "__rg_oom",
+ AllocatorKind::Default => "__rdl_oom",
}
}
+pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable";
+
pub enum AllocatorTy {
Layout,
Ptr,
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 42b8434..7ef39f8 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -607,7 +607,7 @@
/// Returns `true` if the token is an identifier whose name is the given
/// string slice.
pub fn is_ident_named(&self, name: Symbol) -> bool {
- self.ident().map_or(false, |(ident, _)| ident.name == name)
+ self.ident().is_some_and(|(ident, _)| ident.name == name)
}
/// Returns `true` if the token is an interpolated path.
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 15a54fe..50eb921 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -392,8 +392,7 @@
// Small bases are lexed as if they were base 10, e.g, the string
// might be `0b10201`. This will cause the conversion above to fail,
// but these kinds of errors are already reported by the lexer.
- let from_lexer =
- base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
+ let from_lexer = base < 10 && s.chars().any(|c| c.to_digit(10).is_some_and(|d| d >= base));
if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) }
})
}
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 21b2a3c..f63a9bf 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -1,144 +1,29 @@
-ast_lowering_generic_type_with_parentheses =
- parenthesized type parameters may only be used with a `Fn` trait
- .label = only `Fn` traits may use parentheses
-
-ast_lowering_use_angle_brackets = use angle brackets instead
-
-ast_lowering_invalid_abi =
- invalid ABI: found `{$abi}`
- .label = invalid ABI
- .note = invoke `{$command}` for a full list of supported calling conventions.
-
-ast_lowering_invalid_abi_suggestion = did you mean
-
-ast_lowering_assoc_ty_parentheses =
- parenthesized generic arguments cannot be used in associated type constraints
-
-ast_lowering_remove_parentheses = remove these parentheses
-
-ast_lowering_misplaced_impl_trait =
- `impl Trait` only allowed in function and inherent method return types, not in {$position}
-
-ast_lowering_misplaced_assoc_ty_binding =
- associated type bounds are only allowed in where clauses and function signatures, not in {$position}
-
-ast_lowering_underscore_expr_lhs_assign =
- in expressions, `_` can only be used on the left-hand side of an assignment
- .label = `_` not allowed here
-
-ast_lowering_base_expression_double_dot =
- base expression required after `..`
- .label = add a base expression here
-
-ast_lowering_await_only_in_async_fn_and_blocks =
- `await` is only allowed inside `async` functions and blocks
- .label = only allowed inside `async` functions and blocks
-
-ast_lowering_this_not_async = this is not `async`
-
-ast_lowering_generator_too_many_parameters =
- too many parameters for a generator (expected 0 or 1 parameters)
-
-ast_lowering_closure_cannot_be_static = closures cannot be static
-
-ast_lowering_async_non_move_closure_not_supported =
- `async` non-`move` closures with parameters are not currently supported
- .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
-
-ast_lowering_functional_record_update_destructuring_assignment =
- functional record updates are not allowed in destructuring assignments
- .suggestion = consider removing the trailing pattern
-
-ast_lowering_async_generators_not_supported =
- `async` generators are not yet supported
-
-ast_lowering_inline_asm_unsupported_target =
- inline assembly is unsupported on this target
-
-ast_lowering_att_syntax_only_x86 =
- the `att_syntax` option is only supported on x86
-
ast_lowering_abi_specified_multiple_times =
`{$prev_name}` ABI specified multiple times
.label = previously specified here
.note = these ABIs are equivalent on the current target
-ast_lowering_clobber_abi_not_supported =
- `clobber_abi` is not supported on this target
-
-ast_lowering_invalid_abi_clobber_abi =
- invalid ABI for `clobber_abi`
- .note = the following ABIs are supported on this target: {$supported_abis}
-
-ast_lowering_invalid_register =
- invalid register `{$reg}`: {$error}
-
-ast_lowering_invalid_register_class =
- invalid register class `{$reg_class}`: {$error}
-
-ast_lowering_invalid_asm_template_modifier_reg_class =
- invalid asm template modifier for this register class
-
-ast_lowering_argument = argument
-
-ast_lowering_template_modifier = template modifier
-
-ast_lowering_support_modifiers =
- the `{$class_name}` register class supports the following template modifiers: {$modifiers}
-
-ast_lowering_does_not_support_modifiers =
- the `{$class_name}` register class does not support template modifiers
-
-ast_lowering_invalid_asm_template_modifier_const =
- asm template modifiers are not allowed for `const` arguments
-
-ast_lowering_invalid_asm_template_modifier_sym =
- asm template modifiers are not allowed for `sym` arguments
-
-ast_lowering_register_class_only_clobber =
- register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
-
-ast_lowering_register_conflict =
- register `{$reg1_name}` conflicts with register `{$reg2_name}`
- .help = use `lateout` instead of `out` to avoid conflict
-
-ast_lowering_register1 = register `{$reg1_name}`
-
-ast_lowering_register2 = register `{$reg2_name}`
-
-ast_lowering_sub_tuple_binding =
- `{$ident_name} @` is not allowed in a {$ctx}
- .label = this is only allowed in slice patterns
- .help = remove this and bind each tuple field independently
-
-ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
-
-ast_lowering_extra_double_dot =
- `..` can only be used once per {$ctx} pattern
- .label = can only be used once per {$ctx} pattern
-
-ast_lowering_previously_used_here = previously used here
-
-ast_lowering_misplaced_double_dot =
- `..` patterns are not allowed here
- .note = only allowed in tuple, tuple struct, and slice patterns
-
-ast_lowering_misplaced_relax_trait_bound =
- `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-ast_lowering_not_supported_for_lifetime_binder_async_closure =
- `for<...>` binders on `async` closures are not currently supported
-
ast_lowering_arbitrary_expression_in_pattern =
arbitrary expressions aren't allowed in patterns
-ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+ast_lowering_argument = argument
-ast_lowering_trait_fn_async =
- functions in traits cannot be declared `async`
- .label = `async` because of this
- .note = `async` trait functions are not currently supported
- .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ast_lowering_assoc_ty_parentheses =
+ parenthesized generic arguments cannot be used in associated type constraints
+
+ast_lowering_async_generators_not_supported =
+ `async` generators are not yet supported
+
+ast_lowering_async_non_move_closure_not_supported =
+ `async` non-`move` closures with parameters are not currently supported
+ .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+
+ast_lowering_att_syntax_only_x86 =
+ the `att_syntax` option is only supported on x86
+
+ast_lowering_await_only_in_async_fn_and_blocks =
+ `await` is only allowed inside `async` functions and blocks
+ .label = only allowed inside `async` functions and blocks
ast_lowering_bad_return_type_notation_inputs =
argument types not allowed with return type notation
@@ -151,3 +36,118 @@
ast_lowering_bad_return_type_notation_output =
return type not allowed with return type notation
.suggestion = remove the return type
+
+ast_lowering_base_expression_double_dot =
+ base expression required after `..`
+ .label = add a base expression here
+
+ast_lowering_clobber_abi_not_supported =
+ `clobber_abi` is not supported on this target
+
+ast_lowering_closure_cannot_be_static = closures cannot be static
+
+ast_lowering_does_not_support_modifiers =
+ the `{$class_name}` register class does not support template modifiers
+
+ast_lowering_extra_double_dot =
+ `..` can only be used once per {$ctx} pattern
+ .label = can only be used once per {$ctx} pattern
+
+ast_lowering_functional_record_update_destructuring_assignment =
+ functional record updates are not allowed in destructuring assignments
+ .suggestion = consider removing the trailing pattern
+
+ast_lowering_generator_too_many_parameters =
+ too many parameters for a generator (expected 0 or 1 parameters)
+
+ast_lowering_generic_type_with_parentheses =
+ parenthesized type parameters may only be used with a `Fn` trait
+ .label = only `Fn` traits may use parentheses
+
+ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+
+ast_lowering_inline_asm_unsupported_target =
+ inline assembly is unsupported on this target
+
+ast_lowering_invalid_abi =
+ invalid ABI: found `{$abi}`
+ .label = invalid ABI
+ .note = invoke `{$command}` for a full list of supported calling conventions.
+
+ast_lowering_invalid_abi_clobber_abi =
+ invalid ABI for `clobber_abi`
+ .note = the following ABIs are supported on this target: {$supported_abis}
+
+ast_lowering_invalid_abi_suggestion = did you mean
+
+ast_lowering_invalid_asm_template_modifier_const =
+ asm template modifiers are not allowed for `const` arguments
+
+ast_lowering_invalid_asm_template_modifier_reg_class =
+ invalid asm template modifier for this register class
+
+ast_lowering_invalid_asm_template_modifier_sym =
+ asm template modifiers are not allowed for `sym` arguments
+
+ast_lowering_invalid_register =
+ invalid register `{$reg}`: {$error}
+
+ast_lowering_invalid_register_class =
+ invalid register class `{$reg_class}`: {$error}
+
+ast_lowering_misplaced_assoc_ty_binding =
+ associated type bounds are only allowed in where clauses and function signatures, not in {$position}
+
+ast_lowering_misplaced_double_dot =
+ `..` patterns are not allowed here
+ .note = only allowed in tuple, tuple struct, and slice patterns
+
+ast_lowering_misplaced_impl_trait =
+ `impl Trait` only allowed in function and inherent method return types, not in {$position}
+
+ast_lowering_misplaced_relax_trait_bound =
+ `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+ast_lowering_not_supported_for_lifetime_binder_async_closure =
+ `for<...>` binders on `async` closures are not currently supported
+
+ast_lowering_previously_used_here = previously used here
+
+ast_lowering_register1 = register `{$reg1_name}`
+
+ast_lowering_register2 = register `{$reg2_name}`
+
+ast_lowering_register_class_only_clobber =
+ register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
+
+ast_lowering_register_conflict =
+ register `{$reg1_name}` conflicts with register `{$reg2_name}`
+ .help = use `lateout` instead of `out` to avoid conflict
+
+ast_lowering_remove_parentheses = remove these parentheses
+
+ast_lowering_sub_tuple_binding =
+ `{$ident_name} @` is not allowed in a {$ctx}
+ .label = this is only allowed in slice patterns
+ .help = remove this and bind each tuple field independently
+
+ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
+
+ast_lowering_support_modifiers =
+ the `{$class_name}` register class supports the following template modifiers: {$modifiers}
+
+ast_lowering_template_modifier = template modifier
+
+ast_lowering_this_not_async = this is not `async`
+
+ast_lowering_trait_fn_async =
+ functions in traits cannot be declared `async`
+ .label = `async` because of this
+ .note = `async` trait functions are not currently supported
+ .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+ast_lowering_underscore_expr_lhs_assign =
+ in expressions, `_` can only be used on the left-hand side of an assignment
+ .label = `_` not allowed here
+
+ast_lowering_use_angle_brackets = use angle brackets instead
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 211f5cb..8d4f966 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1425,7 +1425,16 @@
DefPathData::ImplTrait,
span,
);
- let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
+
+ // HACK: pprust breaks strings with newlines when the type
+ // gets too long. We don't want these to show up in compiler
+ // output or built artifacts, so replace them here...
+ // Perhaps we should instead format APITs more robustly.
+ let ident = Ident::from_str_and_span(
+ &pprust::ty_to_string(t).replace('\n', " "),
+ span,
+ );
+
let (param, bounds, path) = self.lower_universal_param_and_bounds(
*def_node_id,
span,
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2f41378..2f0ac0c 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -1,48 +1,95 @@
-ast_passes_forbidden_let =
- `let` expressions are not supported here
- .note = only supported directly in conditions of `if` and `while` expressions
- .not_supported_or = `||` operators are not supported in let chain expressions
- .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+ast_passes_assoc_const_without_body =
+ associated constant in `impl` without body
+ .suggestion = provide a definition for the constant
-ast_passes_forbidden_let_stable =
- expected expression, found statement (`let`)
- .note = variable declaration using `let` is a statement
+ast_passes_assoc_fn_without_body =
+ associated function in `impl` without body
+ .suggestion = provide a definition for the function
+
+ast_passes_assoc_type_without_body =
+ associated type in `impl` without body
+ .suggestion = provide a definition for the type
+
+ast_passes_at_least_one_trait = at least one trait must be specified
+
+ast_passes_auto_generic = auto traits cannot have generic parameters
+ .label = auto trait cannot have generic parameters
+ .suggestion = remove the parameters
+
+ast_passes_auto_items = auto traits cannot have associated items
+ .label = {ast_passes_auto_items}
+ .suggestion = remove these associated items
+
+ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
+ .label = {ast_passes_auto_super_lifetime}
+ .suggestion = remove the super traits or lifetime bounds
+
+ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
+
+ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
+ .cannot_have = cannot have a body
+ .invalid = the invalid body
+ .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
+
+ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+
+ast_passes_const_and_async = functions cannot be both `const` and `async`
+ .const = `const` because of this
+ .async = `async` because of this
+ .label = {""}
+
+ast_passes_const_without_body =
+ free constant item without body
+ .suggestion = provide a definition for the constant
+
+ast_passes_constraint_on_negative_bound =
+ associated type constraints not allowed on negative bounds
ast_passes_deprecated_where_clause_location =
where clause not allowed here
-ast_passes_keyword_lifetime =
- lifetimes cannot use keyword names
+ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
+ .label = not supported
+ .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
+ .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
+ .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
-ast_passes_invalid_label =
- invalid label name `{$name}`
+ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
-ast_passes_visibility_not_permitted =
- visibility qualifiers are not permitted here
- .enum_variant = enum variants and their fields always share the visibility of the enum they are in
- .trait_impl = trait items always share the visibility of their trait
- .individual_impl_items = place qualifiers on individual impl items instead
- .individual_foreign_items = place qualifiers on individual foreign items instead
+ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
+ .label = in this `extern` block
+ .suggestion = remove the qualifiers
-ast_passes_trait_fn_const =
- functions in traits cannot be declared const
- .label = functions in traits cannot be const
+ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
+ .label = in this `extern` block
+ .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
-ast_passes_forbidden_lifetime_bound =
- lifetime bounds cannot be used in this context
+ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
-ast_passes_forbidden_non_lifetime_param =
- only lifetime parameters can be used in this context
+ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
+ .suggestion = remove the {$remove_descr}
+ .label = `extern` block begins here
-ast_passes_fn_param_too_many =
- function can not have more than {$max_num_args} arguments
+ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
-ast_passes_fn_param_c_var_args_only =
- C-variadic function must be declared with at least one named argument
+ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
+ .suggestion = remove the attribute
+ .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
+
+ast_passes_fieldless_union = unions cannot have zero fields
+
+ast_passes_fn_body_extern = incorrect function inside `extern` block
+ .cannot_have = cannot have a body
+ .suggestion = remove the invalid body
+ .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+ .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
ast_passes_fn_param_c_var_args_not_last =
`...` must be the last argument of a C-variadic function
+ast_passes_fn_param_c_var_args_only =
+ C-variadic function must be declared with at least one named argument
+
ast_passes_fn_param_doc_comment =
documentation comments cannot be applied to function parameters
.label = doc comments are not allowed here
@@ -55,88 +102,32 @@
.label = not semantically valid as function parameter
.note = associated functions are those in `impl` or `trait` definitions
-ast_passes_forbidden_default =
- `default` is only allowed on items in trait impls
- .label = `default` because of this
-
-ast_passes_assoc_const_without_body =
- associated constant in `impl` without body
- .suggestion = provide a definition for the constant
-
-ast_passes_assoc_fn_without_body =
- associated function in `impl` without body
- .suggestion = provide a definition for the function
-
-ast_passes_assoc_type_without_body =
- associated type in `impl` without body
- .suggestion = provide a definition for the type
-
-ast_passes_const_without_body =
- free constant item without body
- .suggestion = provide a definition for the constant
-
-ast_passes_static_without_body =
- free static item without body
- .suggestion = provide a definition for the static
-
-ast_passes_ty_alias_without_body =
- free type alias without body
- .suggestion = provide a definition for the type
+ast_passes_fn_param_too_many =
+ function can not have more than {$max_num_args} arguments
ast_passes_fn_without_body =
free function without a body
.suggestion = provide a definition for the function
-ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
+ast_passes_forbidden_default =
+ `default` is only allowed on items in trait impls
+ .label = `default` because of this
-ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+ast_passes_forbidden_let =
+ `let` expressions are not supported here
+ .note = only supported directly in conditions of `if` and `while` expressions
+ .not_supported_or = `||` operators are not supported in let chain expressions
+ .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
-ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
- .suggestion = remove the {$remove_descr}
- .label = `extern` block begins here
+ast_passes_forbidden_let_stable =
+ expected expression, found statement (`let`)
+ .note = variable declaration using `let` is a statement
-ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+ast_passes_forbidden_lifetime_bound =
+ lifetime bounds cannot be used in this context
-ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
- .cannot_have = cannot have a body
- .invalid = the invalid body
- .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
-
-ast_passes_fn_body_extern = incorrect function inside `extern` block
- .cannot_have = cannot have a body
- .suggestion = remove the invalid body
- .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
- .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
-
-ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
- .label = in this `extern` block
- .suggestion = remove the qualifiers
-
-ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
- .label = in this `extern` block
- .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
-
-ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
-
-ast_passes_item_underscore = `{$kind}` items in this context need a name
- .label = `_` is not a valid name for this `{$kind}` item
-
-ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
-
-ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
- .help = consider using the `#[path]` attribute to specify filesystem path
-
-ast_passes_auto_generic = auto traits cannot have generic parameters
- .label = auto trait cannot have generic parameters
- .suggestion = remove the parameters
-
-ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
- .label = {ast_passes_auto_super_lifetime}
- .suggestion = remove the super traits or lifetime bounds
-
-ast_passes_auto_items = auto traits cannot have associated items
- .label = {ast_passes_auto_items}
- .suggestion = remove these associated items
+ast_passes_forbidden_non_lifetime_param =
+ only lifetime parameters can be used in this context
ast_passes_generic_before_constraints = generic arguments must come before the first constraint
.constraints = {$constraint_len ->
@@ -156,88 +147,97 @@
*[other] arguments
}
-ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
-
-ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
+ast_passes_generic_default_trailing = generic parameters with a default must be trailing
ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
-ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
- .outer = outer `impl Trait`
- .inner = nested `impl Trait` here
-
-ast_passes_at_least_one_trait = at least one trait must be specified
-
-ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
-
-ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
- .suggestion = reorder the parameters: lifetimes, then consts and types
-
-ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
- .help = use `auto trait Trait {"{}"}` instead
-
-ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
- .negative = negative because of this
- .unsafe = unsafe because of this
+ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+ .help = remove one of these features
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
.because = {$annotation} because of this
.type = inherent impl for this type
.only_trait = only trait implementations may be annotated with {$annotation}
-ast_passes_unsafe_item = {$kind} cannot be declared unsafe
+ast_passes_invalid_label =
+ invalid label name `{$name}`
-ast_passes_fieldless_union = unions cannot have zero fields
+ast_passes_item_underscore = `{$kind}` items in this context need a name
+ .label = `_` is not a valid name for this `{$kind}` item
-ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
- .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+ast_passes_keyword_lifetime =
+ lifetimes cannot use keyword names
-ast_passes_generic_default_trailing = generic parameters with a default must be trailing
+ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
+ .help = consider using the `#[path]` attribute to specify filesystem path
+
+ast_passes_negative_bound_not_supported =
+ negative bounds are not supported
+
+ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
+ .outer = outer `impl Trait`
+ .inner = nested `impl Trait` here
ast_passes_nested_lifetimes = nested quantification of lifetimes
+ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
+
+ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
+ .help = use `auto trait Trait {"{}"}` instead
+
+ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
+
+ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
.note = traits are `?{$path_str}` by default
-ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
+ .suggestion = reorder the parameters: lifetimes, then consts and types
+
+ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
+ .label = pattern not allowed in function without body
+
+ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
+
+ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
+ .label = pattern not allowed in foreign function
+
+ast_passes_show_span = {$msg}
+
+ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+
+ast_passes_static_without_body =
+ free static item without body
+ .suggestion = provide a definition for the static
ast_passes_tilde_const_disallowed = `~const` is not allowed here
.trait = trait objects cannot have `~const` trait bounds
.closure = closures cannot have `~const` trait bounds
.function = this function is not `const`, so it cannot have `~const` trait bounds
-ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
+ast_passes_trait_fn_const =
+ functions in traits cannot be declared const
+ .label = functions in traits cannot be const
-ast_passes_const_and_async = functions cannot be both `const` and `async`
- .const = `const` because of this
- .async = `async` because of this
- .label = {""}
+ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
-ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
- .label = pattern not allowed in foreign function
+ast_passes_ty_alias_without_body =
+ free type alias without body
+ .suggestion = provide a definition for the type
-ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
- .label = pattern not allowed in function without body
+ast_passes_unsafe_item = {$kind} cannot be declared unsafe
-ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
- .label = not supported
- .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
- .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
- .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
+ .negative = negative because of this
+ .unsafe = unsafe because of this
-ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+ast_passes_visibility_not_permitted =
+ visibility qualifiers are not permitted here
+ .enum_variant = enum variants and their fields always share the visibility of the enum they are in
+ .trait_impl = trait items always share the visibility of their trait
+ .individual_impl_items = place qualifiers on individual impl items instead
+ .individual_foreign_items = place qualifiers on individual foreign items instead
-ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
- .suggestion = remove the attribute
- .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
-
-ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
- .help = remove one of these features
-
-ast_passes_show_span = {$msg}
-
-ast_passes_negative_bound_not_supported =
- negative bounds are not supported
-
-ast_passes_constraint_on_negative_bound =
- associated type constraints not allowed on negative bounds
+ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+ .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bf43bbd..04ed276 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -348,7 +348,7 @@
let source_map = self.session.source_map();
let end = source_map.end_point(sp);
- if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
+ if source_map.span_to_snippet(end).is_ok_and(|s| s == ";") {
end
} else {
sp.shrink_to_hi()
@@ -736,11 +736,10 @@
this.visit_expr(&arm.body);
this.visit_pat(&arm.pat);
walk_list!(this, visit_attribute, &arm.attrs);
- if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
+ if let Some(guard) = &arm.guard {
this.with_let_management(None, |this, _| {
- this.visit_expr(guard_expr)
+ this.visit_expr(guard)
});
- return;
}
}
}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 3d5056d..274f931 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -317,8 +317,7 @@
match i.kind {
ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => {
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
- let links_to_llvm =
- link_name.map_or(false, |val| val.as_str().starts_with("llvm."));
+ let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
if links_to_llvm {
gate_feature_post!(
&self,
diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl
index a7f8c99..e6cbbaf 100644
--- a/compiler/rustc_attr/messages.ftl
+++ b/compiler/rustc_attr/messages.ftl
@@ -1,85 +1,3 @@
-attr_expected_one_cfg_pattern =
- expected 1 cfg-pattern
-
-attr_invalid_predicate =
- invalid predicate `{$predicate}`
-
-attr_multiple_item =
- multiple '{$item}' items
-
-attr_incorrect_meta_item =
- incorrect meta item
-
-attr_unknown_meta_item =
- unknown meta item '{$item}'
- .label = expected one of {$expected}
-
-attr_missing_since =
- missing 'since'
-
-attr_missing_note =
- missing 'note'
-
-attr_multiple_stability_levels =
- multiple stability levels
-
-attr_invalid_issue_string =
- `issue` must be a non-zero numeric string or "none"
- .must_not_be_zero = `issue` must not be "0", use "none" instead
- .empty = cannot parse integer from empty string
- .invalid_digit = invalid digit found in string
- .pos_overflow = number too large to fit in target type
- .neg_overflow = number too small to fit in target type
-
-attr_missing_feature =
- missing 'feature'
-
-attr_non_ident_feature =
- 'feature' is not an identifier
-
-attr_missing_issue =
- missing 'issue'
-
-attr_incorrect_repr_format_packed_one_or_zero_arg =
- incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
-
-attr_invalid_repr_hint_no_paren =
- invalid representation hint: `{$name}` does not take a parenthesized argument list
-
-attr_invalid_repr_hint_no_value =
- invalid representation hint: `{$name}` does not take a value
-
-attr_unsupported_literal_generic =
- unsupported literal
-attr_unsupported_literal_cfg_string =
- literal in `cfg` predicate value must be a string
-attr_unsupported_literal_deprecated_string =
- literal in `deprecated` value must be a string
-attr_unsupported_literal_deprecated_kv_pair =
- item in `deprecated` must be a key/value pair
-attr_unsupported_literal_suggestion =
- consider removing the prefix
-
-attr_invalid_repr_align_need_arg =
- invalid `repr(align)` attribute: `align` needs an argument
- .suggestion = supply an argument here
-
-attr_invalid_repr_generic =
- invalid `repr({$repr_arg})` attribute: {$error_part}
-
-attr_incorrect_repr_format_align_one_arg =
- incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
-
-attr_incorrect_repr_format_generic =
- incorrect `repr({$repr_arg})` attribute format
- .suggestion = use parentheses instead
-
-attr_rustc_promotable_pairing =
- `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
-
-attr_rustc_allowed_unstable_pairing =
- `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
-
attr_cfg_predicate_identifier =
`cfg` predicate key must be an identifier
@@ -88,6 +6,9 @@
.help = add `#![feature(deprecated_suggestion)]` to the crate root
.note = see #94785 for more details
+attr_expected_one_cfg_pattern =
+ expected 1 cfg-pattern
+
attr_expected_single_version_literal =
expected single version literal
@@ -100,8 +21,87 @@
attr_expects_features =
`{$name}` expects feature names
+attr_incorrect_meta_item =
+ incorrect meta item
+
+attr_incorrect_repr_format_align_one_arg =
+ incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+
+attr_incorrect_repr_format_generic =
+ incorrect `repr({$repr_arg})` attribute format
+ .suggestion = use parentheses instead
+
+attr_incorrect_repr_format_packed_one_or_zero_arg =
+ incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+
+attr_invalid_issue_string =
+ `issue` must be a non-zero numeric string or "none"
+ .must_not_be_zero = `issue` must not be "0", use "none" instead
+ .empty = cannot parse integer from empty string
+ .invalid_digit = invalid digit found in string
+ .pos_overflow = number too large to fit in target type
+ .neg_overflow = number too small to fit in target type
+
+attr_invalid_predicate =
+ invalid predicate `{$predicate}`
+
+attr_invalid_repr_align_need_arg =
+ invalid `repr(align)` attribute: `align` needs an argument
+ .suggestion = supply an argument here
+
+attr_invalid_repr_generic =
+ invalid `repr({$repr_arg})` attribute: {$error_part}
+
+attr_invalid_repr_hint_no_paren =
+ invalid representation hint: `{$name}` does not take a parenthesized argument list
+
+attr_invalid_repr_hint_no_value =
+ invalid representation hint: `{$name}` does not take a value
+
+attr_missing_feature =
+ missing 'feature'
+
+attr_missing_issue =
+ missing 'issue'
+
+attr_missing_note =
+ missing 'note'
+
+attr_missing_since =
+ missing 'since'
+
+attr_multiple_item =
+ multiple '{$item}' items
+
+attr_multiple_stability_levels =
+ multiple stability levels
+
+attr_non_ident_feature =
+ 'feature' is not an identifier
+
+attr_rustc_allowed_unstable_pairing =
+ `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+
+attr_rustc_promotable_pairing =
+ `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
+
attr_soft_no_args =
`soft` should not have any arguments
+attr_unknown_meta_item =
+ unknown meta item '{$item}'
+ .label = expected one of {$expected}
+
attr_unknown_version_literal =
unknown version literal format, assuming it refers to a future version
+
+attr_unsupported_literal_cfg_string =
+ literal in `cfg` predicate value must be a string
+attr_unsupported_literal_deprecated_kv_pair =
+ item in `deprecated` must be a key/value pair
+attr_unsupported_literal_deprecated_string =
+ literal in `deprecated` value must be a string
+attr_unsupported_literal_generic =
+ unsupported literal
+attr_unsupported_literal_suggestion =
+ consider removing the prefix
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index 4a616dc..67fdb67 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -1,150 +1,23 @@
-borrowck_move_unsized =
- cannot move a value of type `{$ty}`
- .label = the size of `{$ty}` cannot be statically determined
-
-borrowck_higher_ranked_lifetime_error =
- higher-ranked lifetime error
-
-borrowck_could_not_prove =
- could not prove `{$predicate}`
-
-borrowck_could_not_normalize =
- could not normalize `{$value}`
-
-borrowck_higher_ranked_subtype_error =
- higher-ranked subtype error
-
-borrowck_generic_does_not_live_long_enough =
- `{$kind}` does not live long enough
-
-borrowck_move_borrowed =
- cannot move out of `{$desc}` because it is borrowed
-
-borrowck_var_does_not_need_mut =
- variable does not need to be mutable
- .suggestion = remove this `mut`
-
-borrowck_var_cannot_escape_closure =
- captured variable cannot escape `FnMut` closure body
- .note = `FnMut` closures only have access to their captured variables while they are executing...
- .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
-
-borrowck_var_here_defined = variable defined here
-
-borrowck_var_here_captured = variable captured here
-
-borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
-
-borrowck_returned_closure_escaped =
- returns a closure that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_async_block_escaped =
- returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_ref_escaped =
- returns a reference to a captured variable which escapes the closure body
-
-borrowck_lifetime_constraints_error =
- lifetime may not live long enough
-
-borrowck_returned_lifetime_wrong =
- {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
-
-borrowck_returned_lifetime_short =
- {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
-
-borrowck_used_impl_require_static =
- the used `impl` has a `'static` requirement
-
-borrowck_borrow_due_to_use_generator =
- borrow occurs due to use in generator
-
-borrowck_use_due_to_use_generator =
- use occurs due to use in generator
+borrowck_assign_due_to_use_closure =
+ assignment occurs due to use in closure
borrowck_assign_due_to_use_generator =
assign occurs due to use in generator
+borrowck_assign_part_due_to_use_closure =
+ assignment to part occurs due to use in closure
+
borrowck_assign_part_due_to_use_generator =
assign to part occurs due to use in generator
borrowck_borrow_due_to_use_closure =
borrow occurs due to use in closure
-borrowck_use_due_to_use_closure =
- use occurs due to use in closure
-
-borrowck_assign_due_to_use_closure =
- assignment occurs due to use in closure
-
-borrowck_assign_part_due_to_use_closure =
- assignment to part occurs due to use in closure
-
-borrowck_capture_immute =
- capture is immutable because of use here
-
-borrowck_capture_mut =
- capture is mutable because of use here
-
-borrowck_capture_move =
- capture is moved because of use here
-
-borrowck_var_borrow_by_use_place_in_generator =
- {$is_single_var ->
- *[true] borrow occurs
- [false] borrows occur
- } due to use of {$place} in generator
-
-borrowck_var_borrow_by_use_place_in_closure =
- {$is_single_var ->
- *[true] borrow occurs
- [false] borrows occur
- } due to use of {$place} in closure
-
-borrowck_var_borrow_by_use_in_generator =
+borrowck_borrow_due_to_use_generator =
borrow occurs due to use in generator
-borrowck_var_borrow_by_use_in_closure =
- borrow occurs due to use in closure
-
-borrowck_var_move_by_use_place_in_generator =
- move occurs due to use of {$place} in generator
-
-borrowck_var_move_by_use_place_in_closure =
- move occurs due to use of {$place} in closure
-
-borrowck_var_move_by_use_in_generator =
- move occurs due to use in generator
-
-borrowck_var_move_by_use_in_closure =
- move occurs due to use in closure
-
-borrowck_partial_var_move_by_use_in_generator =
- variable {$is_partial ->
- [true] partially moved
- *[false] moved
- } due to use in generator
-
-borrowck_partial_var_move_by_use_in_closure =
- variable {$is_partial ->
- [true] partially moved
- *[false] moved
- } due to use in closure
-
-borrowck_var_first_borrow_by_use_place_in_generator =
- first borrow occurs due to use of {$place} in generator
-
-borrowck_var_first_borrow_by_use_place_in_closure =
- first borrow occurs due to use of {$place} in closure
-
-borrowck_var_second_borrow_by_use_place_in_generator =
- second borrow occurs due to use of {$place} in generator
-
-borrowck_var_second_borrow_by_use_place_in_closure =
- second borrow occurs due to use of {$place} in closure
-
-borrowck_var_mutable_borrow_by_use_place_in_closure =
- mutable borrow occurs due to use of {$place} in closure
+borrowck_calling_operator_moves_lhs =
+ calling this operator moves the left-hand side
borrowck_cannot_move_when_borrowed =
cannot move out of {$place ->
@@ -160,11 +33,67 @@
*[other] {$value_place}
} occurs here
-borrowck_opaque_type_non_generic_param =
- expected generic {$kind} parameter, found `{$ty}`
- .label = {STREQ($ty, "'static") ->
- [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
- *[other] this generic parameter must be used with a generic {$kind} parameter
+borrowck_capture_immute =
+ capture is immutable because of use here
+
+borrowck_capture_move =
+ capture is moved because of use here
+
+borrowck_capture_mut =
+ capture is mutable because of use here
+
+borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
+
+borrowck_closure_invoked_twice =
+ closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+
+borrowck_closure_moved_twice =
+ closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+
+borrowck_consider_borrow_type_contents =
+ help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+
+borrowck_could_not_normalize =
+ could not normalize `{$value}`
+
+borrowck_could_not_prove =
+ could not prove `{$predicate}`
+
+borrowck_func_take_self_moved_place =
+ `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+
+borrowck_generic_does_not_live_long_enough =
+ `{$kind}` does not live long enough
+
+borrowck_higher_ranked_lifetime_error =
+ higher-ranked lifetime error
+
+borrowck_higher_ranked_subtype_error =
+ higher-ranked subtype error
+
+borrowck_lifetime_constraints_error =
+ lifetime may not live long enough
+
+borrowck_move_borrowed =
+ cannot move out of `{$desc}` because it is borrowed
+
+borrowck_move_out_place_here =
+ {$place} is moved here
+
+borrowck_move_unsized =
+ cannot move a value of type `{$ty}`
+ .label = the size of `{$ty}` cannot be statically determined
+
+borrowck_moved_a_fn_once_in_call =
+ this value implements `FnOnce`, which causes it to be moved when called
+
+borrowck_moved_due_to_await =
+ {$place_name} {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to this {$is_loop_message ->
+ [true] await, in previous iteration of loop
+ *[false] await
}
borrowck_moved_due_to_call =
@@ -176,15 +105,6 @@
*[false] call
}
-borrowck_moved_due_to_usage_in_operator =
- {$place_name} {$is_partial ->
- [true] partially moved
- *[false] moved
- } due to usage in {$is_loop_message ->
- [true] operator, in previous iteration of loop
- *[false] operator
- }
-
borrowck_moved_due_to_implicit_into_iter_call =
{$place_name} {$is_partial ->
[true] partially moved
@@ -203,13 +123,74 @@
*[false] call
}
-borrowck_moved_due_to_await =
+borrowck_moved_due_to_usage_in_operator =
{$place_name} {$is_partial ->
[true] partially moved
*[false] moved
- } due to this {$is_loop_message ->
- [true] await, in previous iteration of loop
- *[false] await
+ } due to usage in {$is_loop_message ->
+ [true] operator, in previous iteration of loop
+ *[false] operator
+ }
+
+borrowck_opaque_type_non_generic_param =
+ expected generic {$kind} parameter, found `{$ty}`
+ .label = {STREQ($ty, "'static") ->
+ [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+ *[other] this generic parameter must be used with a generic {$kind} parameter
+ }
+
+borrowck_partial_var_move_by_use_in_closure =
+ variable {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to use in closure
+
+borrowck_partial_var_move_by_use_in_generator =
+ variable {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to use in generator
+
+borrowck_returned_async_block_escaped =
+ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_closure_escaped =
+ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_lifetime_short =
+ {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
+
+borrowck_returned_lifetime_wrong =
+ {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
+
+borrowck_returned_ref_escaped =
+ returns a reference to a captured variable which escapes the closure body
+
+borrowck_suggest_create_freash_reborrow =
+ consider reborrowing the `Pin` instead of moving it
+
+borrowck_suggest_iterate_over_slice =
+ consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+
+borrowck_ty_no_impl_copy =
+ {$is_partial_move ->
+ [true] partial move
+ *[false] move
+ } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+
+borrowck_use_due_to_use_closure =
+ use occurs due to use in closure
+
+borrowck_use_due_to_use_generator =
+ use occurs due to use in generator
+
+borrowck_used_impl_require_static =
+ the used `impl` has a `'static` requirement
+
+borrowck_value_capture_here =
+ value captured {$is_within ->
+ [true] here by generator
+ *[false] here
}
borrowck_value_moved_here =
@@ -224,41 +205,60 @@
*[false] {""}
}
-borrowck_consider_borrow_type_contents =
- help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+borrowck_var_borrow_by_use_in_closure =
+ borrow occurs due to use in closure
-borrowck_moved_a_fn_once_in_call =
- this value implements `FnOnce`, which causes it to be moved when called
+borrowck_var_borrow_by_use_in_generator =
+ borrow occurs due to use in generator
-borrowck_calling_operator_moves_lhs =
- calling this operator moves the left-hand side
+borrowck_var_borrow_by_use_place_in_closure =
+ {$is_single_var ->
+ *[true] borrow occurs
+ [false] borrows occur
+ } due to use of {$place} in closure
-borrowck_func_take_self_moved_place =
- `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+borrowck_var_borrow_by_use_place_in_generator =
+ {$is_single_var ->
+ *[true] borrow occurs
+ [false] borrows occur
+ } due to use of {$place} in generator
-borrowck_suggest_iterate_over_slice =
- consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+borrowck_var_cannot_escape_closure =
+ captured variable cannot escape `FnMut` closure body
+ .note = `FnMut` closures only have access to their captured variables while they are executing...
+ .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
-borrowck_suggest_create_freash_reborrow =
- consider reborrowing the `Pin` instead of moving it
+borrowck_var_does_not_need_mut =
+ variable does not need to be mutable
+ .suggestion = remove this `mut`
-borrowck_value_capture_here =
- value captured {$is_within ->
- [true] here by generator
- *[false] here
- }
+borrowck_var_first_borrow_by_use_place_in_closure =
+ first borrow occurs due to use of {$place} in closure
-borrowck_move_out_place_here =
- {$place} is moved here
+borrowck_var_first_borrow_by_use_place_in_generator =
+ first borrow occurs due to use of {$place} in generator
-borrowck_closure_invoked_twice =
- closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+borrowck_var_here_captured = variable captured here
-borrowck_closure_moved_twice =
- closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+borrowck_var_here_defined = variable defined here
-borrowck_ty_no_impl_copy =
- {$is_partial_move ->
- [true] partial move
- *[false] move
- } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+borrowck_var_move_by_use_in_closure =
+ move occurs due to use in closure
+
+borrowck_var_move_by_use_in_generator =
+ move occurs due to use in generator
+
+borrowck_var_move_by_use_place_in_closure =
+ move occurs due to use of {$place} in closure
+
+borrowck_var_move_by_use_place_in_generator =
+ move occurs due to use of {$place} in generator
+
+borrowck_var_mutable_borrow_by_use_place_in_closure =
+ mutable borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_closure =
+ second borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_generator =
+ second borrow occurs due to use of {$place} in generator
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 4824f63..6be20b0 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -30,7 +30,7 @@
/// Map from local to all the borrows on that local.
pub local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>,
- pub(crate) locals_state_at_exit: LocalsStateAtExit,
+ pub locals_state_at_exit: LocalsStateAtExit,
}
impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
@@ -153,7 +153,7 @@
self.activation_map.get(&location).map_or(&[], |activations| &activations[..])
}
- pub(crate) fn len(&self) -> usize {
+ pub fn len(&self) -> usize {
self.location_map.len()
}
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 3451b7d..d257145 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -3,22 +3,96 @@
//! This file provides API for compiler consumers.
use rustc_hir::def_id::LocalDefId;
-use rustc_index::IndexSlice;
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_middle::mir::Body;
+use rustc_index::{IndexSlice, IndexVec};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::mir::{Body, Promoted};
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::TyCtxt;
+use std::rc::Rc;
+
+use crate::borrow_set::BorrowSet;
pub use super::{
+ constraints::OutlivesConstraint,
+ dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows},
facts::{AllFacts as PoloniusInput, RustcFacts},
location::{LocationTable, RichLocation},
nll::PoloniusOutput,
- BodyWithBorrowckFacts,
+ place_ext::PlaceExt,
+ places_conflict::{places_conflict, PlaceConflictBias},
+ region_infer::RegionInferenceContext,
};
-/// This function computes Polonius facts for the given body. It makes a copy of
-/// the body because it needs to regenerate the region identifiers. This function
-/// should never be invoked during a typical compilation session due to performance
-/// issues with Polonius.
+/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
+///
+/// If executing under `-Z polonius` the choice here has no effect, and everything as if
+/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
+/// will be retrieved.
+#[derive(Debug, Copy, Clone)]
+pub enum ConsumerOptions {
+ /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
+ /// and [`RegionInferenceContext`]. If you would like the body only, use
+ /// [`TyCtxt::mir_promoted`].
+ ///
+ /// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
+ RegionInferenceContext,
+ /// The recommended option. Retrieves the maximal amount of information
+ /// without significant slowdowns.
+ ///
+ /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
+ /// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that
+ /// would be given to Polonius. Critically, this does not run Polonius, which
+ /// one may want to avoid due to performance issues on large bodies.
+ PoloniusInputFacts,
+ /// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts),
+ /// and additionally runs Polonius to calculate the [`PoloniusOutput`].
+ PoloniusOutputFacts,
+}
+
+impl ConsumerOptions {
+ /// Should the Polonius input facts be computed?
+ pub(crate) fn polonius_input(&self) -> bool {
+ matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts)
+ }
+ /// Should we run Polonius and collect the output facts?
+ pub(crate) fn polonius_output(&self) -> bool {
+ matches!(self, Self::PoloniusOutputFacts)
+ }
+}
+
+/// A `Body` with information computed by the borrow checker. This struct is
+/// intended to be consumed by compiler consumers.
+///
+/// We need to include the MIR body here because the region identifiers must
+/// match the ones in the Polonius facts.
+pub struct BodyWithBorrowckFacts<'tcx> {
+ /// A mir body that contains region identifiers.
+ pub body: Body<'tcx>,
+ /// The mir bodies of promoteds.
+ pub promoted: IndexVec<Promoted, Body<'tcx>>,
+ /// The set of borrows occurring in `body` with data about them.
+ pub borrow_set: Rc<BorrowSet<'tcx>>,
+ /// Context generated during borrowck, intended to be passed to
+ /// [`calculate_borrows_out_of_scope_at_location`].
+ pub region_inference_context: Rc<RegionInferenceContext<'tcx>>,
+ /// The table that maps Polonius points to locations in the table.
+ /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
+ /// or [`ConsumerOptions::PoloniusOutputFacts`].
+ pub location_table: Option<LocationTable>,
+ /// Polonius input facts.
+ /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
+ /// or [`ConsumerOptions::PoloniusOutputFacts`].
+ pub input_facts: Option<Box<PoloniusInput>>,
+ /// Polonius output facts. Populated when using
+ /// [`ConsumerOptions::PoloniusOutputFacts`].
+ pub output_facts: Option<Rc<PoloniusOutput>>,
+}
+
+/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
+/// determine which facts are returned. This function makes a copy of the body because
+/// it needs to regenerate the region identifiers. It should never be invoked during a
+/// typical compilation session due to the unnecessary overhead of returning
+/// [`BodyWithBorrowckFacts`].
///
/// Note:
/// * This function will panic if the required body was already stolen. This
@@ -28,10 +102,14 @@
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
-pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
+pub fn get_body_with_borrowck_facts(
+ tcx: TyCtxt<'_>,
+ def: LocalDefId,
+ options: ConsumerOptions,
+) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
- *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
+ *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
}
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 167f245..2daa82a 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -156,10 +156,10 @@
&mut self,
borrow_index: BorrowIndex,
borrow_region: RegionVid,
- location: Location,
+ first_location: Location,
) {
// We visit one BB at a time. The complication is that we may start in the
- // middle of the first BB visited (the one containing `location`), in which
+ // middle of the first BB visited (the one containing `first_location`), in which
// case we may have to later on process the first part of that BB if there
// is a path back to its start.
@@ -168,61 +168,58 @@
// `visited` once they are added to `stack`, before they are actually
// processed, because this avoids the need to look them up again on
// completion.
- self.visited.insert(location.block);
+ self.visited.insert(first_location.block);
- let mut first_lo = location.statement_index;
- let first_hi = self.body[location.block].statements.len();
+ let first_block = first_location.block;
+ let mut first_lo = first_location.statement_index;
+ let first_hi = self.body[first_block].statements.len();
- self.visit_stack.push(StackEntry { bb: location.block, lo: first_lo, hi: first_hi });
+ self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
- while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
- // If we process the first part of the first basic block (i.e. we encounter that block
- // for the second time), we no longer have to visit its successors again.
- let mut finished_early = bb == location.block && hi != first_hi;
- for i in lo..=hi {
- let location = Location { block: bb, statement_index: i };
+ 'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
+ if let Some(kill_stmt) =
+ self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
+ {
+ let kill_location = Location { block: bb, statement_index: kill_stmt };
// If region does not contain a point at the location, then add to list and skip
// successor locations.
- if !self.regioncx.region_contains(borrow_region, location) {
- debug!("borrow {:?} gets killed at {:?}", borrow_index, location);
- self.borrows_out_of_scope_at_location
- .entry(location)
- .or_default()
- .push(borrow_index);
- finished_early = true;
- break;
- }
+ debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
+ self.borrows_out_of_scope_at_location
+ .entry(kill_location)
+ .or_default()
+ .push(borrow_index);
+ continue 'preorder;
}
- if !finished_early {
- // Add successor BBs to the work list, if necessary.
- let bb_data = &self.body[bb];
- debug_assert!(hi == bb_data.statements.len());
- for succ_bb in bb_data.terminator().successors() {
- if !self.visited.insert(succ_bb) {
- if succ_bb == location.block && first_lo > 0 {
- // `succ_bb` has been seen before. If it wasn't
- // fully processed, add its first part to `stack`
- // for processing.
- self.visit_stack.push(StackEntry {
- bb: succ_bb,
- lo: 0,
- hi: first_lo - 1,
- });
+ // If we process the first part of the first basic block (i.e. we encounter that block
+ // for the second time), we no longer have to visit its successors again.
+ if bb == first_block && hi != first_hi {
+ continue;
+ }
- // And update this entry with 0, to represent the
- // whole BB being processed.
- first_lo = 0;
- }
- } else {
- // succ_bb hasn't been seen before. Add it to
- // `stack` for processing.
- self.visit_stack.push(StackEntry {
- bb: succ_bb,
- lo: 0,
- hi: self.body[succ_bb].statements.len(),
- });
+ // Add successor BBs to the work list, if necessary.
+ let bb_data = &self.body[bb];
+ debug_assert!(hi == bb_data.statements.len());
+ for succ_bb in bb_data.terminator().successors() {
+ if !self.visited.insert(succ_bb) {
+ if succ_bb == first_block && first_lo > 0 {
+ // `succ_bb` has been seen before. If it wasn't
+ // fully processed, add its first part to `stack`
+ // for processing.
+ self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
+
+ // And update this entry with 0, to represent the
+ // whole BB being processed.
+ first_lo = 0;
}
+ } else {
+ // succ_bb hasn't been seen before. Add it to
+ // `stack` for processing.
+ self.visit_stack.push(StackEntry {
+ bb: succ_bb,
+ lo: 0,
+ hi: self.body[succ_bb].statements.len(),
+ });
}
}
}
@@ -231,27 +228,32 @@
}
}
+pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
+ body: &Body<'tcx>,
+ regioncx: &RegionInferenceContext<'tcx>,
+ borrow_set: &BorrowSet<'tcx>,
+) -> FxIndexMap<Location, Vec<BorrowIndex>> {
+ let mut prec = OutOfScopePrecomputer::new(body, regioncx);
+ for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
+ let borrow_region = borrow_data.region;
+ let location = borrow_data.reserve_location;
+
+ prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
+ }
+
+ prec.borrows_out_of_scope_at_location
+}
+
impl<'a, 'tcx> Borrows<'a, 'tcx> {
- pub(crate) fn new(
+ pub fn new(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
nonlexical_regioncx: &'a RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
- let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx);
- for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
- let borrow_region = borrow_data.region;
- let location = borrow_data.reserve_location;
-
- prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
- }
-
- Borrows {
- tcx,
- body,
- borrow_set,
- borrows_out_of_scope_at_location: prec.borrows_out_of_scope_at_location,
- }
+ let borrows_out_of_scope_at_location =
+ calculate_borrows_out_of_scope_at_location(body, nonlexical_regioncx, borrow_set);
+ Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}
pub fn location(&self, idx: BorrowIndex) -> &Location {
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 84f75ca..f41795d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -128,7 +128,7 @@
}
}
-impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
+impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
// We can't rerun custom type ops.
UniverseInfo::other()
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 04b8174..15d73ed 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1635,34 +1635,6 @@
})
}
- /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
- ///
- /// Depending on the origin of the StorageDeadOrDrop, this may be
- /// reported as either a drop or an illegal mutation of a borrowed value.
- /// The latter is preferred when the this is a drop triggered by a
- /// reassignment, as it's more user friendly to report a problem with the
- /// explicit assignment than the implicit drop.
- #[instrument(level = "debug", skip(self))]
- pub(crate) fn report_storage_dead_or_drop_of_borrowed(
- &mut self,
- location: Location,
- place_span: (Place<'tcx>, Span),
- borrow: &BorrowData<'tcx>,
- ) {
- // It's sufficient to check the last desugaring as Replace is the last
- // one to be applied.
- if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
- self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
- } else {
- self.report_borrowed_value_does_not_live_long_enough(
- location,
- borrow,
- place_span,
- Some(WriteKind::StorageDeadOrDrop),
- )
- }
- }
-
/// This means that some data referenced by `borrow` needs to live
/// past the point where the StorageDeadOrDrop of `place` occurs.
/// This is usually interpreted as meaning that `place` has too
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index d0cb112..1d430a9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -118,7 +118,7 @@
let path_span = path_span.unwrap();
// path_span is only present in the case of closure capture
assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
- if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) {
+ if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
let path_label = "used here by closure";
let capture_kind_label = message;
err.span_label(
@@ -224,12 +224,9 @@
if info.tail_result_is_ignored {
// #85581: If the first mutable borrow's scope contains
// the second borrow, this suggestion isn't helpful.
- if !multiple_borrow_span
- .map(|(old, new)| {
- old.to(info.span.shrink_to_hi()).contains(new)
- })
- .unwrap_or(false)
- {
+ if !multiple_borrow_span.is_some_and(|(old, new)| {
+ old.to(info.span.shrink_to_hi()).contains(new)
+ }) {
err.span_suggestion_verbose(
info.span.shrink_to_hi(),
"consider adding semicolon after the expression so its \
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 7fc8eb1..20370e4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1156,7 +1156,7 @@
ty::Adt(def, ..) => Some(def.did()),
_ => None,
});
- let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+ let is_option_or_result = parent_self_ty.is_some_and(|def_id| {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
if is_option_or_result && maybe_reinitialized_locations_is_empty {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6286033..d0e17bf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -289,8 +289,7 @@
.body
.local_decls
.get(local)
- .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
- .unwrap_or(false) =>
+ .is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) =>
{
let decl = &self.body.local_decls[local];
err.span_label(span, format!("cannot {act}"));
@@ -443,7 +442,7 @@
.sess
.source_map()
.span_to_snippet(span)
- .map_or(false, |snippet| snippet.starts_with("&mut ")) =>
+ .is_ok_and(|snippet| snippet.starts_with("&mut ")) =>
{
err.span_label(span, format!("cannot {act}"));
err.span_suggestion(
@@ -642,13 +641,8 @@
let Some(hir::Node::Item(item)) = node else { return; };
let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
let body = self.infcx.tcx.hir().body(body_id);
- let mut assign_span = span;
- // Drop desugaring is done at MIR build so it's not in the HIR
- if let Some(DesugaringKind::Replace) = span.desugaring_kind() {
- assign_span.remove_mark();
- }
- let mut v = V { assign_span, err, ty, suggested: false };
+ let mut v = V { assign_span: span, err, ty, suggested: false };
v.visit_body(body);
if !v.suggested {
err.help(format!(
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index ffba605..b6eb9ae 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -125,8 +125,7 @@
|(r, _)| {
self.constraints_to_add
.get(r)
- .map(|r_outlived| r_outlived.as_slice().contains(fr))
- .unwrap_or(false)
+ .is_some_and(|r_outlived| r_outlived.as_slice().contains(fr))
},
);
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 863c92a..b2ff25e 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -46,7 +46,7 @@
all_facts: &'cx mut AllFacts,
location_table: &'cx LocationTable,
body: &'cx Body<'tcx>,
- dominators: Dominators<BasicBlock>,
+ dominators: &'cx Dominators<BasicBlock>,
borrow_set: &'cx BorrowSet<'tcx>,
}
@@ -112,11 +112,13 @@
TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(location, discr);
}
- TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
+ TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace } => {
+ let write_kind =
+ if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
self.access_place(
location,
*drop_place,
- (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
+ (AccessDepth::Drop, Write(write_kind)),
LocalMutationIsAllowed::Yes,
);
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index eb25d45..a53ea10 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -26,7 +26,7 @@
use rustc_index::bit_set::ChunkedBitSet;
use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::{
- DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
+ InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
@@ -36,6 +36,7 @@
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
use rustc_middle::query::Providers;
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
use rustc_session::lint::builtin::UNUSED_MUT;
use rustc_span::{Span, Symbol};
@@ -43,7 +44,6 @@
use either::Either;
use smallvec::SmallVec;
-use std::cell::OnceCell;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ops::Deref;
@@ -62,7 +62,7 @@
use self::diagnostics::{AccessKind, RegionName};
use self::location::LocationTable;
use self::prefixes::PrefixSet;
-use facts::AllFacts;
+use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
use self::path_utils::*;
@@ -144,7 +144,7 @@
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
- let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
+ let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
debug!("mir_borrowck done");
tcx.arena.alloc(opt_closure_req)
@@ -152,15 +152,15 @@
/// Perform the actual borrow checking.
///
-/// If `return_body_with_facts` is true, then return the body with non-erased
-/// region ids on which the borrow checking was performed together with Polonius
-/// facts.
+/// Use `consumer_options: None` for the default behavior of returning
+/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
+/// to the given [`ConsumerOptions`].
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
- return_body_with_facts: bool,
+ consumer_options: Option<ConsumerOptions>,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.def_id().expect_local();
debug!(?def);
@@ -241,8 +241,6 @@
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
- let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.unstable_opts.polonius;
-
// Compute non-lexical lifetimes.
let nll::NllOutput {
regioncx,
@@ -262,7 +260,7 @@
&mdpe.move_data,
&borrow_set,
&upvars,
- use_polonius,
+ consumer_options,
);
// Dump MIR results into a file, if that is enabled. This let us
@@ -331,7 +329,6 @@
used_mut: Default::default(),
used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set),
- dominators: Default::default(),
upvars: Vec::new(),
local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
region_names: RefCell::default(),
@@ -360,7 +357,6 @@
used_mut: Default::default(),
used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set),
- dominators: Default::default(),
upvars,
local_names,
region_names: RefCell::default(),
@@ -444,13 +440,16 @@
tainted_by_errors,
};
- let body_with_facts = if return_body_with_facts {
- let output_facts = mbcx.polonius_output.expect("Polonius output was not computed");
+ let body_with_facts = if consumer_options.is_some() {
+ let output_facts = mbcx.polonius_output;
Some(Box::new(BodyWithBorrowckFacts {
body: body_owned,
- input_facts: *polonius_input.expect("Polonius input facts were not generated"),
+ promoted,
+ borrow_set,
+ region_inference_context: regioncx,
+ location_table: polonius_input.as_ref().map(|_| location_table_owned),
+ input_facts: polonius_input,
output_facts,
- location_table: location_table_owned,
}))
} else {
None
@@ -461,22 +460,6 @@
(result, body_with_facts)
}
-/// A `Body` with information computed by the borrow checker. This struct is
-/// intended to be consumed by compiler consumers.
-///
-/// We need to include the MIR body here because the region identifiers must
-/// match the ones in the Polonius facts.
-pub struct BodyWithBorrowckFacts<'tcx> {
- /// A mir body that contains region identifiers.
- pub body: Body<'tcx>,
- /// Polonius input facts.
- pub input_facts: AllFacts,
- /// Polonius output facts.
- pub output_facts: Rc<self::nll::PoloniusOutput>,
- /// The table that maps Polonius points to locations in the table.
- pub location_table: LocationTable,
-}
-
pub struct BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) infcx: &'cx InferCtxt<'tcx>,
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
@@ -591,9 +574,6 @@
/// The set of borrows extracted from the MIR
borrow_set: Rc<BorrowSet<'tcx>>,
- /// Dominators for MIR
- dominators: OnceCell<Dominators<BasicBlock>>,
-
/// Information about upvars not necessarily preserved in types or MIR
upvars: Vec<Upvar<'tcx>>,
@@ -705,17 +685,19 @@
TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(loc, (discr, span), flow_state);
}
- TerminatorKind::Drop { place, target: _, unwind: _ } => {
+ TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
debug!(
"visit_terminator_drop \
loc: {:?} term: {:?} place: {:?} span: {:?}",
loc, term, place, span
);
+ let write_kind =
+ if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
self.access_place(
loc,
(*place, span),
- (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
+ (AccessDepth::Drop, Write(write_kind)),
LocalMutationIsAllowed::Yes,
flow_state,
);
@@ -905,6 +887,7 @@
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum WriteKind {
StorageDeadOrDrop,
+ Replace,
MutableBorrow(BorrowKind),
Mutate,
Move,
@@ -1152,13 +1135,21 @@
this.buffer_error(err);
}
WriteKind::StorageDeadOrDrop => this
- .report_storage_dead_or_drop_of_borrowed(location, place_span, borrow),
+ .report_borrowed_value_does_not_live_long_enough(
+ location,
+ borrow,
+ place_span,
+ Some(WriteKind::StorageDeadOrDrop),
+ ),
WriteKind::Mutate => {
this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
}
WriteKind::Move => {
this.report_move_out_while_borrowed(location, place_span, borrow)
}
+ WriteKind::Replace => {
+ this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
+ }
}
Control::Break
}
@@ -2002,12 +1993,14 @@
Reservation(
WriteKind::Move
+ | WriteKind::Replace
| WriteKind::StorageDeadOrDrop
| WriteKind::MutableBorrow(BorrowKind::Shared)
| WriteKind::MutableBorrow(BorrowKind::Shallow),
)
| Write(
WriteKind::Move
+ | WriteKind::Replace
| WriteKind::StorageDeadOrDrop
| WriteKind::MutableBorrow(BorrowKind::Shared)
| WriteKind::MutableBorrow(BorrowKind::Shallow),
@@ -2269,7 +2262,8 @@
}
fn dominators(&self) -> &Dominators<BasicBlock> {
- self.dominators.get_or_init(|| self.body.basic_blocks.dominators())
+ // `BasicBlocks` computes dominators on-demand and caches them.
+ self.body.basic_blocks.dominators()
}
}
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index b6ccf92..889acb3 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -27,6 +27,7 @@
use crate::{
borrow_set::BorrowSet,
constraint_generation,
+ consumers::ConsumerOptions,
diagnostics::RegionErrors,
facts::{AllFacts, AllFactsExt, RustcFacts},
invalidation,
@@ -165,10 +166,14 @@
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
upvars: &[Upvar<'tcx>],
- use_polonius: bool,
+ consumer_options: Option<ConsumerOptions>,
) -> NllOutput<'tcx> {
+ let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
+ || infcx.tcx.sess.opts.unstable_opts.polonius;
+ let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
+ || infcx.tcx.sess.opts.unstable_opts.polonius;
let mut all_facts =
- (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
+ (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
@@ -189,7 +194,7 @@
move_data,
elements,
upvars,
- use_polonius,
+ polonius_input,
);
if let Some(all_facts) = &mut all_facts {
@@ -284,7 +289,7 @@
all_facts.write_to_dir(dir_path, location_table).unwrap();
}
- if use_polonius {
+ if polonius_output {
let algorithm =
env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
let algorithm = Algorithm::from_str(&algorithm).unwrap();
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index 85d207b..d521d0d 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -7,7 +7,7 @@
use rustc_middle::ty::{self, TyCtxt};
/// Extension methods for the `Place` type.
-pub(crate) trait PlaceExt<'tcx> {
+pub trait PlaceExt<'tcx> {
/// Returns `true` if we can safely ignore borrows of this place.
/// This is true whenever there is no action that the user can do
/// to the place `self` that would invalidate the borrow. This is true
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 918fb2d..25c485b 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -16,7 +16,7 @@
/// being run in the calling context, the conservative choice is to assume the compared indices
/// are disjoint (and therefore, do not overlap).
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub(crate) enum PlaceConflictBias {
+pub enum PlaceConflictBias {
Overlap,
NoOverlap,
}
@@ -24,7 +24,7 @@
/// Helper function for checking if places conflict with a mutable borrow and deep access depth.
/// This is used to check for places conflicting outside of the borrow checking code (such as in
/// dataflow).
-pub(crate) fn places_conflict<'tcx>(
+pub fn places_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
borrow_place: Place<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 8fbe814..50b246b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -12,7 +12,7 @@
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{
- Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
+ BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
TerminatorKind,
};
@@ -585,6 +585,11 @@
self.universal_regions.to_region_vid(r)
}
+ /// Returns an iterator over all the outlives constraints.
+ pub fn outlives_constraints(&self) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ {
+ self.constraints.outlives().iter().copied()
+ }
+
/// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) {
self.universal_regions.annotate(tcx, err)
@@ -598,6 +603,20 @@
self.scc_values.contains(scc, p)
}
+ /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
+ ///
+ /// Panics if called before `solve()` executes.
+ pub(crate) fn first_non_contained_inclusive(
+ &self,
+ r: RegionVid,
+ block: BasicBlock,
+ start: usize,
+ end: usize,
+ ) -> Option<usize> {
+ let scc = self.constraint_sccs.scc(r);
+ self.scc_values.first_non_contained_inclusive(scc, block, start, end)
+ }
+
/// Returns access to the value of `r` for debugging purposes.
pub(crate) fn region_value_str(&self, r: RegionVid) -> String {
let scc = self.constraint_sccs.scc(r);
@@ -698,7 +717,7 @@
#[instrument(skip(self, _body), level = "debug")]
fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
debug!("constraints={:#?}", {
- let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
+ let mut constraints: Vec<_> = self.outlives_constraints().collect();
constraints.sort_by_key(|c| (c.sup, c.sub));
constraints
.into_iter()
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index e9b5c47..7fc89e8 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -2,9 +2,10 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
+use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::TyCtxtInferExt as _;
-use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause};
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 193e206..9290e74 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -159,7 +159,7 @@
/// Returns `true` if the region `r` contains the given element.
pub(crate) fn contains(&self, row: N, location: Location) -> bool {
let index = self.elements.point_from_location(location);
- self.points.row(row).map_or(false, |r| r.contains(index))
+ self.points.row(row).is_some_and(|r| r.contains(index))
}
/// Returns an iterator of all the elements contained by the region `r`
@@ -283,6 +283,22 @@
elem.contained_in_row(self, r)
}
+ /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
+ pub(crate) fn first_non_contained_inclusive(
+ &self,
+ r: N,
+ block: BasicBlock,
+ start: usize,
+ end: usize,
+ ) -> Option<usize> {
+ let row = self.points.row(r)?;
+ let block = self.elements.entry_point(block);
+ let start = block.plus(start);
+ let end = block.plus(end);
+ let first_unset = row.first_unset_in(start..=end)?;
+ Some(first_unset.index() - block.index())
+ }
+
/// `self[to] |= values[from]`, essentially: that is, take all the
/// elements for the region `from` from `values` and add them to
/// the region `to` in `self`.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index b27d5d2..f527eee 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -1,13 +1,13 @@
use std::fmt;
-use rustc_infer::infer::{canonical::Canonical, InferOk};
+use rustc_errors::ErrorGuaranteed;
+use rustc_infer::infer::canonical::Canonical;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
-use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+use rustc_trait_selection::traits::ObligationCause;
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
@@ -30,14 +30,15 @@
locations: Locations,
category: ConstraintCategory<'tcx>,
op: Op,
- ) -> Fallible<R>
+ ) -> Result<R, ErrorGuaranteed>
where
Op: type_op::TypeOp<'tcx, Output = R>,
Op::ErrorInfo: ToUniverseInfo<'tcx>,
{
let old_universe = self.infcx.universe();
- let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
+ let TypeOpOutput { output, constraints, error_info } =
+ op.fully_perform(self.infcx, locations.span(self.body))?;
debug!(?output, ?constraints);
@@ -135,14 +136,11 @@
) {
let param_env = self.param_env;
let predicate = predicate.to_predicate(self.tcx());
- self.fully_perform_op(
+ let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
locations,
category,
param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
- )
- .unwrap_or_else(|NoSolution| {
- span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
- })
+ );
}
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
@@ -163,15 +161,12 @@
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{
let param_env = self.param_env;
- self.fully_perform_op(
+ let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
location.to_locations(),
category,
param_env.and(type_op::normalize::Normalize::new(value)),
- )
- .unwrap_or_else(|NoSolution| {
- span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
- value
- })
+ );
+ result.unwrap_or(value)
}
#[instrument(skip(self), level = "debug")]
@@ -181,18 +176,11 @@
user_ty: ty::UserType<'tcx>,
span: Span,
) {
- self.fully_perform_op(
+ let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
- )
- .unwrap_or_else(|err| {
- span_mirbug!(
- self,
- span,
- "ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
- );
- });
+ );
}
/// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
@@ -219,27 +207,17 @@
let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env;
- let op = |infcx: &'_ _| {
- let ocx = ObligationCtxt::new_in_snapshot(infcx);
- let user_ty = ocx.normalize(&cause, param_env, user_ty);
- ocx.eq(&cause, param_env, user_ty, mir_ty)?;
- if !ocx.select_all_or_error().is_empty() {
- return Err(NoSolution);
- }
- Ok(InferOk { value: (), obligations: vec![] })
- };
-
- self.fully_perform_op(
+ let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
- type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()),
- )
- .unwrap_or_else(|err| {
- span_mirbug!(
- self,
- span,
- "ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
- );
- });
+ type_op::custom::CustomTypeOp::new(
+ |ocx| {
+ let user_ty = ocx.normalize(&cause, param_env, user_ty);
+ ocx.eq(&cause, param_env, user_ty, mir_ty)?;
+ Ok(())
+ },
+ "ascribe_user_type_skip_wf",
+ ),
+ );
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index bd01c0b..c8ec125 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,7 @@
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
@@ -243,18 +243,11 @@
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
- .fully_perform(self.infcx)
- .unwrap_or_else(|_| {
- let guar = self
- .infcx
- .tcx
- .sess
- .delay_span_bug(span, format!("failed to normalize {:?}", ty));
- TypeOpOutput {
- output: self.infcx.tcx.ty_error(guar),
- constraints: None,
- error_info: None,
- }
+ .fully_perform(self.infcx, span)
+ .unwrap_or_else(|guar| TypeOpOutput {
+ output: self.infcx.tcx.ty_error(guar),
+ constraints: None,
+ error_info: None,
});
if let Some(c) = constraints_normalize {
constraints.push(c)
@@ -324,7 +317,7 @@
let TypeOpOutput { output: bounds, constraints, .. } = self
.param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
- .fully_perform(self.infcx)
+ .fully_perform(self.infcx, DUMMY_SP)
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
debug!(?bounds, ?constraints);
self.add_outlives_bounds(bounds);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 9731b10..eb02604 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,8 +3,9 @@
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc_middle::traits::query::DropckOutlivesResult;
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
-use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
+use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
use std::rc::Rc;
@@ -568,10 +569,15 @@
) -> DropData<'tcx> {
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
- let param_env = typeck.param_env;
- let TypeOpOutput { output, constraints, .. } =
- param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
-
- DropData { dropck_result: output, region_constraint_data: constraints }
+ match typeck
+ .param_env
+ .and(DropckOutlives::new(dropped_ty))
+ .fully_perform(typeck.infcx, DUMMY_SP)
+ {
+ Ok(TypeOpOutput { output, constraints, .. }) => {
+ DropData { dropck_result: output, region_constraint_data: constraints }
+ }
+ Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+ }
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index fa4bc92..51a84ce 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -10,6 +10,7 @@
use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -20,12 +21,13 @@
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{
- InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
+ InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
};
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -41,13 +43,14 @@
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
-use rustc_trait_selection::traits::query::Fallible;
+
use rustc_trait_selection::traits::PredicateObligation;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
+use crate::renumber::RegionCtxt;
use crate::session_diagnostics::MoveUnsized;
use crate::{
borrow_set::BorrowSet,
@@ -183,17 +186,19 @@
&mut borrowck_context,
);
- let errors_reported = {
- let mut verifier = TypeVerifier::new(&mut checker, promoted);
- verifier.visit_body(&body);
- verifier.errors_reported
- };
-
- if !errors_reported {
- // if verifier failed, don't do further checks to avoid ICEs
- checker.typeck_mir(body);
+ // FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
+ // predefined opaques in the typeck root.
+ // FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
+ // the HIR typeck map defining usages back to their definition params,
+ // they won't actually match up with the usages in this body...
+ if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
+ checker.register_predefined_opaques_in_new_solver();
}
+ let mut verifier = TypeVerifier::new(&mut checker, promoted);
+ verifier.visit_body(&body);
+
+ checker.typeck_mir(body);
checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
checker.check_signature_annotation(&body);
@@ -213,24 +218,22 @@
let opaque_type_values = opaque_type_values
.into_iter()
.map(|(opaque_type_key, decl)| {
- checker
- .fully_perform_op(
- Locations::All(body.span),
- ConstraintCategory::OpaqueType,
- CustomTypeOp::new(
- |infcx| {
- infcx.register_member_constraints(
- param_env,
- opaque_type_key,
- decl.hidden_type.ty,
- decl.hidden_type.span,
- );
- Ok(InferOk { value: (), obligations: vec![] })
- },
- || "opaque_type_map".to_string(),
- ),
- )
- .unwrap();
+ let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
+ Locations::All(body.span),
+ ConstraintCategory::OpaqueType,
+ CustomTypeOp::new(
+ |ocx| {
+ ocx.infcx.register_member_constraints(
+ param_env,
+ opaque_type_key,
+ decl.hidden_type.ty,
+ decl.hidden_type.span,
+ );
+ Ok(())
+ },
+ "opaque_type_map",
+ ),
+ );
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_non_region_infer() {
@@ -294,7 +297,6 @@
cx: &'a mut TypeChecker<'b, 'tcx>,
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
last_span: Span,
- errors_reported: bool,
}
impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
@@ -383,13 +385,11 @@
};
};
- if !self.errors_reported {
- let promoted_body = &self.promoted[promoted];
- self.sanitize_promoted(promoted_body, location);
+ let promoted_body = &self.promoted[promoted];
+ self.sanitize_promoted(promoted_body, location);
- let promoted_ty = promoted_body.return_ty();
- check_err(self, promoted_body, ty, promoted_ty);
- }
+ let promoted_ty = promoted_body.return_ty();
+ check_err(self, promoted_body, ty, promoted_ty);
} else {
self.cx.ascribe_user_type(
constant.literal.ty(),
@@ -483,9 +483,6 @@
for local_decl in &body.local_decls {
self.sanitize_type(local_decl, local_decl.ty);
}
- if self.errors_reported {
- return;
- }
self.super_body(body);
}
}
@@ -495,7 +492,7 @@
cx: &'a mut TypeChecker<'b, 'tcx>,
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
) -> Self {
- TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
+ TypeVerifier { promoted, last_span: cx.body.span, cx }
}
fn body(&self) -> &Body<'tcx> {
@@ -529,7 +526,6 @@
for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
if let Err(guar) = place_ty.ty.error_reported() {
- assert!(self.errors_reported);
return PlaceTy::from_ty(self.tcx().ty_error(guar));
}
}
@@ -593,10 +589,7 @@
self.visit_body(&promoted_body);
- if !self.errors_reported {
- // if verifier failed, don't do further checks to avoid ICEs
- self.cx.typeck_mir(promoted_body);
- }
+ self.cx.typeck_mir(promoted_body);
self.cx.body = parent_body;
// Merge the outlives constraints back in, at the given location.
@@ -762,7 +755,6 @@
}
fn error(&mut self) -> Ty<'tcx> {
- self.errors_reported = true;
self.tcx().ty_error_misc()
}
@@ -1041,6 +1033,57 @@
checker
}
+ pub(super) fn register_predefined_opaques_in_new_solver(&mut self) {
+ // OK to use the identity substitutions for each opaque type key, since
+ // we remap opaques from HIR typeck back to their definition params.
+ let opaques: Vec<_> = self
+ .infcx
+ .tcx
+ .typeck(self.body.source.def_id().expect_local())
+ .concrete_opaque_types
+ .iter()
+ .map(|(&def_id, &hidden_ty)| {
+ let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
+ (ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
+ })
+ .collect();
+
+ let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
+ self.infcx.next_nll_region_var(
+ NllRegionVariableOrigin::Existential { from_forall: false },
+ || RegionCtxt::Unknown,
+ )
+ });
+
+ let param_env = self.param_env;
+ let result = self.fully_perform_op(
+ Locations::All(self.body.span),
+ ConstraintCategory::OpaqueType,
+ CustomTypeOp::new(
+ |ocx| {
+ for (key, hidden_ty) in renumbered_opaques {
+ ocx.register_infer_ok_obligations(
+ ocx.infcx.register_hidden_type_in_new_solver(
+ key,
+ param_env,
+ hidden_ty.ty,
+ )?,
+ );
+ }
+ Ok(())
+ },
+ "register pre-defined opaques",
+ ),
+ );
+
+ if result.is_err() {
+ self.infcx.tcx.sess.delay_span_bug(
+ self.body.span,
+ "failed re-defining predefined opaques in mir typeck",
+ );
+ }
+ }
+
fn body(&self) -> &Body<'tcx> {
self.body
}
@@ -1091,7 +1134,7 @@
sup: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory<'tcx>,
- ) -> Fallible<()> {
+ ) -> Result<(), NoSolution> {
// Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics.
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
@@ -1104,7 +1147,7 @@
found: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory<'tcx>,
- ) -> Fallible<()> {
+ ) -> Result<(), NoSolution> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
}
@@ -1116,7 +1159,7 @@
user_ty: &UserTypeProjection,
locations: Locations,
category: ConstraintCategory<'tcx>,
- ) -> Fallible<()> {
+ ) -> Result<(), NoSolution> {
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
trace!(?annotated_type);
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@@ -2712,10 +2755,20 @@
/// constraints in our `InferCtxt`
type ErrorInfo = InstantiateOpaqueType<'tcx>;
- fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
- let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
- Ok(InferOk { value: (), obligations: self.obligations.clone() })
- })?;
+ fn fully_perform(
+ mut self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+ let (mut output, region_constraints) = scrape_region_constraints(
+ infcx,
+ |ocx| {
+ ocx.register_obligations(self.obligations.clone());
+ Ok(())
+ },
+ "InstantiateOpaqueType",
+ span,
+ )?;
self.region_constraints = Some(region_constraints);
output.error_info = Some(self);
Ok(output)
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 7158c62..8c4bfb2 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,12 +1,13 @@
+use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
-use rustc_trait_selection::traits::query::Fallible;
use crate::constraints::OutlivesConstraint;
use crate::diagnostics::UniverseInfo;
@@ -30,7 +31,7 @@
b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory<'tcx>,
- ) -> Fallible<()> {
+ ) -> Result<(), NoSolution> {
TypeRelating::new(
self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
@@ -47,7 +48,7 @@
b: ty::SubstsRef<'tcx>,
locations: Locations,
category: ConstraintCategory<'tcx>,
- ) -> Fallible<()> {
+ ) -> Result<(), NoSolution> {
TypeRelating::new(
self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
@@ -185,17 +186,15 @@
}
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
- self.type_checker
- .fully_perform_op(
- self.locations,
- self.category,
- InstantiateOpaqueType {
- obligations,
- // These fields are filled in during execution of the operation
- base_universe: None,
- region_constraints: None,
- },
- )
- .unwrap();
+ let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
+ self.locations,
+ self.category,
+ InstantiateOpaqueType {
+ obligations,
+ // These fields are filled in during execution of the operation
+ base_universe: None,
+ region_constraints: None,
+ },
+ );
}
}
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 3b458b1..f00cd39 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -1,62 +1,101 @@
-builtin_macros_requires_cfg_pattern =
- macro requires a cfg-pattern as an argument
- .label = cfg-pattern required
-
-builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
-
builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
+builtin_macros_asm_clobber_abi = clobber_abi
+builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
+builtin_macros_asm_clobber_outputs = generic outputs
+
+builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
+ .label = previously here
+ .arg = duplicate argument
+
+builtin_macros_asm_expected_comma = expected token: `,`
+ .label = expected `,`
+
+builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
+ [true] options
+ *[false] clobber_abi, options
+ }, or additional template string
+
+builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
+
+builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
+
+builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
+
+builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
+
+builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
+ .label = this option was already provided
+ .suggestion = remove this option
+
+builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
+ .pos = positional argument
+ .named = named argument
+ .explicit = explicit register argument
+
+builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
+
+builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
+
+builtin_macros_asm_requires_template = requires at least a template string argument
+
+builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
+
+builtin_macros_asm_underscore_input = _ cannot be used for input operands
+
+builtin_macros_assert_missing_comma = unexpected string literal
+ .suggestion = try adding a comma
+
builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
.label = boolean expression required
builtin_macros_assert_requires_expression = macro requires an expression as an argument
.suggestion = try removing semicolon
-builtin_macros_assert_missing_comma = unexpected string literal
- .suggestion = try adding a comma
+builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
+ .label = not applicable here
+ .label2 = not a `struct`, `enum` or `union`
-builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
-builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
-builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cannot_derive_union = this trait cannot be derived for unions
+
builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not
-builtin_macros_concat_bytestr = cannot concatenate a byte string literal
-
-builtin_macros_concat_missing_literal = expected a literal
- .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
-
-builtin_macros_concat_bytes_missing_literal = expected a byte literal
- .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
-
-builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
- .byte_char = try using a byte character
- .byte_str = try using a byte string
- .number_array = try wrapping the number in an array
-
-builtin_macros_concat_bytes_oob = numeric literal is out of bounds
-
-builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
-
+builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
+builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
.note = byte strings are treated as arrays of bytes
.help = try flattening the array
builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
-builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
-builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
+builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
+ .byte_char = try using a byte character
+ .byte_str = try using a byte string
+ .number_array = try wrapping the number in an array
+
+builtin_macros_concat_bytes_missing_literal = expected a byte literal
+ .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+
+builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
+
+builtin_macros_concat_bytes_oob = numeric literal is out of bounds
+
+builtin_macros_concat_bytestr = cannot concatenate a byte string literal
+
builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
-builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
- .label = not applicable here
- .label2 = not a `struct`, `enum` or `union`
+builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
+builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
+builtin_macros_concat_missing_literal = expected a literal
+ .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
-builtin_macros_unexpected_lit = expected path to a trait, found literal
- .label = not a trait
- .str_lit = try using `#[derive({$sym})]`
- .other = for example, write `#[derive(Debug)]` for `Debug`
+builtin_macros_default_arg = `#[default]` attribute does not accept a value
+ .suggestion = try using `#[default]`
+
+builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
.suggestion = remove the arguments
@@ -64,66 +103,38 @@
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value
-builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
-
-builtin_macros_cannot_derive_union = this trait cannot be derived for unions
-
-builtin_macros_no_default_variant = no default declared
- .help = make a unit variant default by placing `#[default]` above it
- .suggestion = make `{$ident}` default
-
-builtin_macros_multiple_defaults = multiple declared defaults
- .label = first default
- .additional = additional default
- .note = only one variant can be default
- .suggestion = make `{$ident}` default
-
-builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
- .help = consider a manual implementation of `Default`
-
-builtin_macros_non_exhaustive_default = default variant must be exhaustive
- .label = declared `#[non_exhaustive]` here
- .help = consider a manual implementation of `Default`
-
-builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
- .note = only one `#[default]` attribute is needed
- .label = `#[default]` used here
- .label_again = `#[default]` used again here
- .help = try removing {$only_one ->
- [true] this
- *[false] these
- }
-
-builtin_macros_default_arg = `#[default]` attribute does not accept a value
- .suggestion = try using `#[default]`
-
-builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
-
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
.other = use `std::env::var("{$var}")` to read the variable at run time
-builtin_macros_format_requires_string = requires at least a format string argument
+builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
+
+builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
.label1 = previously here
.label2 = duplicate argument
+builtin_macros_format_no_arg_named = there is no argument named `{$name}`
+ .note = did you intend to capture a variable `{$name}` from the surrounding scope?
+ .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+builtin_macros_format_pos_mismatch = {$n} positional {$n ->
+ [one] argument
+ *[more] arguments
+ } in format string, but {$desc}
+
builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
.label = positional arguments must be before named arguments
.named_args = named argument
+builtin_macros_format_requires_string = requires at least a format string argument
+
builtin_macros_format_string_invalid = invalid format string: {$desc}
.label = {$label1} in format string
.note = {$note}
.second_label = {$label}
-builtin_macros_sugg = consider using a positional formatting argument instead
-
-builtin_macros_format_no_arg_named = there is no argument named `{$name}`
- .note = did you intend to capture a variable `{$name}` from the surrounding scope?
- .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
-
builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
.note = the only appropriate formatting traits are:
- ``, which uses the `Display` trait
@@ -145,60 +156,49 @@
builtin_macros_format_unused_args = multiple unused formatting arguments
.label = multiple missing formatting specifiers
-builtin_macros_format_pos_mismatch = {$n} positional {$n ->
- [one] argument
- *[more] arguments
- } in format string, but {$desc}
+builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
-builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
+builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
+ .note = only one `#[default]` attribute is needed
+ .label = `#[default]` used here
+ .label_again = `#[default]` used again here
+ .help = try removing {$only_one ->
+ [true] this
+ *[false] these
+ }
+
+builtin_macros_multiple_defaults = multiple declared defaults
+ .label = first default
+ .additional = additional default
+ .note = only one variant can be default
+ .suggestion = make `{$ident}` default
+
+builtin_macros_no_default_variant = no default declared
+ .help = make a unit variant default by placing `#[default]` above it
+ .suggestion = make `{$ident}` default
+
+builtin_macros_non_exhaustive_default = default variant must be exhaustive
+ .label = declared `#[non_exhaustive]` here
+ .help = consider a manual implementation of `Default`
+
+builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
+ .help = consider a manual implementation of `Default`
+
+builtin_macros_requires_cfg_pattern =
+ macro requires a cfg-pattern as an argument
+ .label = cfg-pattern required
+
+builtin_macros_sugg = consider using a positional formatting argument instead
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
.label = `{$kind}` because of this
-builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
-
-builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
-
-builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
-
-builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
-
-builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
-
-builtin_macros_asm_requires_template = requires at least a template string argument
-
-builtin_macros_asm_expected_comma = expected token: `,`
- .label = expected `,`
-
-builtin_macros_asm_underscore_input = _ cannot be used for input operands
-
-builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
-
-builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
- [true] options
- *[false] clobber_abi, options
- }, or additional template string
-
-builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
- .label = previously here
- .arg = duplicate argument
-
-builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
- .pos = positional argument
- .named = named argument
- .explicit = explicit register argument
-
-builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
-
-builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
-
-builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
-builtin_macros_asm_clobber_abi = clobber_abi
-builtin_macros_asm_clobber_outputs = generic outputs
-
-builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
- .label = this option was already provided
- .suggestion = remove this option
+builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
+
+builtin_macros_unexpected_lit = expected path to a trait, found literal
+ .label = not a trait
+ .str_lit = try using `#[derive({$sym})]`
+ .other = for example, write `#[derive(Debug)]` for `Debug`
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index ea830a0..b619e80 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -233,10 +233,19 @@
ExprKind::Cast(local_expr, _) => {
self.manage_cond_expr(local_expr);
}
+ ExprKind::If(local_expr, _, _) => {
+ self.manage_cond_expr(local_expr);
+ }
ExprKind::Index(prefix, suffix) => {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
+ ExprKind::Let(_, local_expr, _) => {
+ self.manage_cond_expr(local_expr);
+ }
+ ExprKind::Match(local_expr, _) => {
+ self.manage_cond_expr(local_expr);
+ }
ExprKind::MethodCall(call) => {
for arg in &mut call.args {
self.manage_cond_expr(arg);
@@ -295,17 +304,14 @@
| ExprKind::Continue(_)
| ExprKind::Err
| ExprKind::Field(_, _)
- | ExprKind::FormatArgs(_)
| ExprKind::ForLoop(_, _, _, _)
- | ExprKind::If(_, _, _)
+ | ExprKind::FormatArgs(_)
| ExprKind::IncludedBytes(..)
| ExprKind::InlineAsm(_)
- | ExprKind::OffsetOf(_, _)
- | ExprKind::Let(_, _, _)
| ExprKind::Lit(_)
| ExprKind::Loop(_, _, _)
| ExprKind::MacCall(_)
- | ExprKind::Match(_, _)
+ | ExprKind::OffsetOf(_, _)
| ExprKind::Path(_, _)
| ExprKind::Ret(_)
| ExprKind::Try(_)
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index ed91cea..49401e9 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -119,7 +119,7 @@
self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr
|| attr
.ident()
- .map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr);
+ .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr);
}
}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 866cc5a..f0d378d 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -1,7 +1,7 @@
use crate::util::check_builtin_macro_attribute;
use rustc_ast::expand::allocator::{
- AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
+ global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
@@ -40,8 +40,7 @@
// Generate a bunch of new items using the AllocFnFactory
let span = ecx.with_def_site_ctxt(item.span);
- let f =
- AllocFnFactory { span, ty_span, kind: AllocatorKind::Global, global: item.ident, cx: ecx };
+ let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx };
// Generate item statements for the allocator methods.
let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
@@ -63,7 +62,6 @@
struct AllocFnFactory<'a, 'b> {
span: Span,
ty_span: Span,
- kind: AllocatorKind,
global: Ident,
cx: &'b ExtCtxt<'a>,
}
@@ -92,7 +90,7 @@
}));
let item = self.cx.item(
self.span,
- Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
+ Ident::from_str_and_span(&global_fn_name(method.name), self.span),
self.attrs(),
kind,
);
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 73a3e33..84e09cf 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -432,11 +432,9 @@
let is_cold = if fn_sig.abi() == Abi::RustCold {
true
} else {
- instance
- .map(|inst| {
- fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD)
- })
- .unwrap_or(false)
+ instance.is_some_and(|inst| {
+ fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD)
+ })
};
if is_cold {
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
@@ -470,7 +468,7 @@
};
// Pass the caller location for `#[track_caller]`.
- if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) {
+ if instance.is_some_and(|inst| inst.def.requires_caller_location(fx.tcx)) {
let caller_location = fx.get_caller_location(source_info);
args.push(CallArgument { value: caller_location, is_owned: false });
}
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 2c246ce..d4b1ae2 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -3,10 +3,12 @@
use crate::prelude::*;
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+ ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
/// Returns whether an allocator shim was created
pub(crate) fn codegen(
@@ -34,41 +36,43 @@
) {
let usize_ty = module.target_config().pointer_type();
- for method in ALLOCATOR_METHODS {
- let mut arg_tys = Vec::with_capacity(method.inputs.len());
- for ty in method.inputs.iter() {
- match *ty {
- AllocatorTy::Layout => {
- arg_tys.push(usize_ty); // size
- arg_tys.push(usize_ty); // align
+ if kind == AllocatorKind::Default {
+ for method in ALLOCATOR_METHODS {
+ let mut arg_tys = Vec::with_capacity(method.inputs.len());
+ for ty in method.inputs.iter() {
+ match *ty {
+ AllocatorTy::Layout => {
+ arg_tys.push(usize_ty); // size
+ arg_tys.push(usize_ty); // align
+ }
+ AllocatorTy::Ptr => arg_tys.push(usize_ty),
+ AllocatorTy::Usize => arg_tys.push(usize_ty),
+
+ AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
- AllocatorTy::Ptr => arg_tys.push(usize_ty),
- AllocatorTy::Usize => arg_tys.push(usize_ty),
-
- AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
+ let output = match method.output {
+ AllocatorTy::ResultPtr => Some(usize_ty),
+ AllocatorTy::Unit => None,
+
+ AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+ panic!("invalid allocator output")
+ }
+ };
+
+ let sig = Signature {
+ call_conv: module.target_config().default_call_conv,
+ params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
+ returns: output.into_iter().map(AbiParam::new).collect(),
+ };
+ crate::common::create_wrapper_function(
+ module,
+ unwind_context,
+ sig,
+ &global_fn_name(method.name),
+ &default_fn_name(method.name),
+ );
}
- let output = match method.output {
- AllocatorTy::ResultPtr => Some(usize_ty),
- AllocatorTy::Unit => None,
-
- AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
- panic!("invalid allocator output")
- }
- };
-
- let sig = Signature {
- call_conv: module.target_config().default_call_conv,
- params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
- returns: output.into_iter().map(AbiParam::new).collect(),
- };
- crate::common::create_wrapper_function(
- module,
- unwind_context,
- sig,
- &format!("__rust_{}", method.name),
- &kind.fn_name(method.name),
- );
}
let sig = Signature {
@@ -81,7 +85,7 @@
unwind_context,
sig,
"__rust_alloc_error_handler",
- &alloc_error_handler_kind.fn_name(sym::oom),
+ &alloc_error_handler_name(alloc_error_handler_kind),
);
let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
@@ -90,4 +94,11 @@
let val = oom_strategy.should_panic();
data_ctx.define(Box::new([val]));
module.define_data(data_id, &data_ctx).unwrap();
+
+ let data_id =
+ module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap();
+ let mut data_ctx = DataContext::new();
+ data_ctx.set_align(1);
+ data_ctx.define(Box::new([0]));
+ module.define_data(data_id, &data_ctx).unwrap();
}
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 25fd5ca..fcfa0b8 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -473,7 +473,7 @@
| TerminatorKind::GeneratorDrop => {
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
}
- TerminatorKind::Drop { place, target, unwind: _ } => {
+ TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
let drop_place = codegen_place(fx, *place);
crate::abi::codegen_drop(fx, source_info, drop_place);
@@ -630,11 +630,11 @@
let to_ty = fx.monomorphize(to_ty);
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
- ty.builtin_deref(true)
- .map(|ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
+ ty.builtin_deref(true).is_some_and(
+ |ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
has_ptr_meta(fx.tcx, pointee_ty)
- })
- .unwrap_or(false)
+ },
+ )
}
if is_fat_ptr(fx, from_ty) {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index ccb3a0c..5eaa988 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -413,11 +413,7 @@
// Note: must be kept in sync with get_caller_location from cg_ssa
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
- let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, mut span: Span| {
- // Remove `Inlined` marks as they pollute `expansion_cause`.
- while span.is_inlined() {
- span.remove_mark();
- }
+ let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = fx.tcx.const_caller_location((
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 0a94a08..97bc8ef 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -1,68 +1,68 @@
-codegen_gcc_unwinding_inline_asm =
- GCC backend does not support unwinding from inline asm
-
-codegen_gcc_lto_not_supported =
- LTO is not supported. You may get a linker error.
+codegen_gcc_invalid_minimum_alignment =
+ invalid minimum global alignment: {$err}
codegen_gcc_invalid_monomorphization_basic_integer =
invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
-codegen_gcc_invalid_monomorphization_invalid_float_vector =
- invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
-
-codegen_gcc_invalid_monomorphization_not_float =
- invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
-
-codegen_gcc_invalid_monomorphization_unrecognized =
- invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
-codegen_gcc_invalid_monomorphization_unsupported_element =
- invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
-
-codegen_gcc_invalid_monomorphization_invalid_bitmask =
- invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_gcc_invalid_monomorphization_simd_shuffle =
- invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
codegen_gcc_invalid_monomorphization_expected_simd =
invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
+codegen_gcc_invalid_monomorphization_inserted_type =
+ invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_invalid_bitmask =
+ invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_gcc_invalid_monomorphization_invalid_float_vector =
+ invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
+
codegen_gcc_invalid_monomorphization_mask_type =
invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+codegen_gcc_invalid_monomorphization_mismatched_lengths =
+ invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_gcc_invalid_monomorphization_not_float =
+ invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
+
+codegen_gcc_invalid_monomorphization_return_element =
+ invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_integer_type =
+ invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
codegen_gcc_invalid_monomorphization_return_length =
invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
codegen_gcc_invalid_monomorphization_return_length_input_type =
invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
-codegen_gcc_invalid_monomorphization_return_element =
- invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
codegen_gcc_invalid_monomorphization_return_type =
invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
-codegen_gcc_invalid_monomorphization_inserted_type =
- invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+codegen_gcc_invalid_monomorphization_simd_shuffle =
+ invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-codegen_gcc_invalid_monomorphization_return_integer_type =
- invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_mismatched_lengths =
- invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+codegen_gcc_invalid_monomorphization_unrecognized =
+ invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
codegen_gcc_invalid_monomorphization_unsupported_cast =
invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+codegen_gcc_invalid_monomorphization_unsupported_element =
+ invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
+
codegen_gcc_invalid_monomorphization_unsupported_operation =
invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
-codegen_gcc_invalid_minimum_alignment =
- invalid minimum global alignment: {$err}
+codegen_gcc_lto_not_supported =
+ LTO is not supported. You may get a linker error.
codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
.help = add the missing features in a `target_feature` attribute
+
+codegen_gcc_unwinding_inline_asm =
+ GCC backend does not support unwinding from inline asm
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index 4bad33e..13f8819 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,11 +1,13 @@
#[cfg(feature="master")]
use gccjit::FnAttribute;
use gccjit::{FunctionType, GlobalKind, ToRValue};
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+ ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
use crate::GccContext;
@@ -22,69 +24,71 @@
let i8p = i8.make_pointer();
let void = context.new_type::<()>();
- for method in ALLOCATOR_METHODS {
- let mut types = Vec::with_capacity(method.inputs.len());
- for ty in method.inputs.iter() {
- match *ty {
- AllocatorTy::Layout => {
- types.push(usize);
- types.push(usize);
+ if kind == AllocatorKind::Default {
+ for method in ALLOCATOR_METHODS {
+ let mut types = Vec::with_capacity(method.inputs.len());
+ for ty in method.inputs.iter() {
+ match *ty {
+ AllocatorTy::Layout => {
+ types.push(usize);
+ types.push(usize);
+ }
+ AllocatorTy::Ptr => types.push(i8p),
+ AllocatorTy::Usize => types.push(usize),
+
+ AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
- AllocatorTy::Ptr => types.push(i8p),
- AllocatorTy::Usize => types.push(usize),
-
- AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
- }
- let output = match method.output {
- AllocatorTy::ResultPtr => Some(i8p),
- AllocatorTy::Unit => None,
+ let output = match method.output {
+ AllocatorTy::ResultPtr => Some(i8p),
+ AllocatorTy::Unit => None,
- AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
- panic!("invalid allocator output")
+ AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+ panic!("invalid allocator output")
+ }
+ };
+ let name = global_fn_name(method.name);
+
+ let args: Vec<_> = types.iter().enumerate()
+ .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+ .collect();
+ let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
+
+ if tcx.sess.target.options.default_hidden_visibility {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
}
- };
- let name = format!("__rust_{}", method.name);
+ if tcx.sess.must_emit_unwind_tables() {
+ // TODO(antoyo): emit unwind tables.
+ }
- let args: Vec<_> = types.iter().enumerate()
- .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
- .collect();
- let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
-
- if tcx.sess.target.options.default_hidden_visibility {
+ let callee = default_fn_name(method.name);
+ let args: Vec<_> = types.iter().enumerate()
+ .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+ .collect();
+ let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
#[cfg(feature="master")]
- func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
- }
- if tcx.sess.must_emit_unwind_tables() {
- // TODO(antoyo): emit unwind tables.
- }
+ callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
- let callee = kind.fn_name(method.name);
- let args: Vec<_> = types.iter().enumerate()
- .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
- .collect();
- let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
- #[cfg(feature="master")]
- callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
+ let block = func.new_block("entry");
- let block = func.new_block("entry");
+ let args = args
+ .iter()
+ .enumerate()
+ .map(|(i, _)| func.get_param(i as i32).to_rvalue())
+ .collect::<Vec<_>>();
+ let ret = context.new_call(None, callee, &args);
+ //llvm::LLVMSetTailCall(ret, True);
+ if output.is_some() {
+ block.end_with_return(None, ret);
+ }
+ else {
+ block.end_with_void_return(None);
+ }
- let args = args
- .iter()
- .enumerate()
- .map(|(i, _)| func.get_param(i as i32).to_rvalue())
- .collect::<Vec<_>>();
- let ret = context.new_call(None, callee, &args);
- //llvm::LLVMSetTailCall(ret, True);
- if output.is_some() {
- block.end_with_return(None, ret);
+ // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
+ // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
}
- else {
- block.end_with_void_return(None);
- }
-
- // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
- // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
}
let types = [usize, usize];
@@ -99,7 +103,7 @@
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
}
- let callee = alloc_error_handler_kind.fn_name(sym::oom);
+ let callee = alloc_error_handler_name(alloc_error_handler_kind);
let args: Vec<_> = types.iter().enumerate()
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();
@@ -123,4 +127,9 @@
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
let value = context.new_rvalue_from_int(i8, value as i32);
global.global_set_initializer_rvalue(value);
+
+ let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
+ let global = context.new_global(None, GlobalKind::Exported, i8, name);
+ let value = context.new_rvalue_from_int(i8, 0);
+ global.global_set_initializer_rvalue(value);
}
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index d776347..55622fd 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,3 +1,73 @@
+codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
+
+codegen_llvm_dlltool_fail_import_library =
+ Dlltool could not create import library: {$stdout}
+ {$stderr}
+
+codegen_llvm_dynamic_linking_with_lto =
+ cannot prefer dynamic linking when performing LTO
+ .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_llvm_error_calling_dlltool =
+ Error calling dlltool '{$dlltool_path}': {$error}
+
+codegen_llvm_error_creating_import_library =
+ Error creating import library for {$lib_name}: {$error}
+
+codegen_llvm_error_writing_def_file =
+ Error writing .DEF file: {$error}
+
+codegen_llvm_from_llvm_diag = {$message}
+
+codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
+codegen_llvm_invalid_minimum_alignment =
+ invalid minimum global alignment: {$err}
+
+codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
+codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+
+codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
+
+codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
+
+codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
+
+codegen_llvm_missing_features =
+ add the missing features in a `target_feature` attribute
+
+codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
+codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+
+codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
+codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
+
+codegen_llvm_parse_target_machine_config =
+ failed to parse target machine config to target machine: {$error}
+
+codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
+codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
+codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
+
+codegen_llvm_run_passes = failed to run LLVM passes
+codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
+
+codegen_llvm_sanitizer_memtag_requires_mte =
+ `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
+
+codegen_llvm_serialize_module = failed to serialize module {$name}
+codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+
+codegen_llvm_symbol_already_defined =
+ symbol `{$symbol_name}` is already defined
+
+codegen_llvm_target_feature_disable_or_enable =
+ the target features {$features} must all be either enabled or disabled together
+
+codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
+codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
+
codegen_llvm_unknown_ctarget_feature =
unknown feature specified for `-Ctarget-feature`: `{$feature}`
.note = it is still passed through to the codegen backend
@@ -8,83 +78,13 @@
unknown feature specified for `-Ctarget-feature`: `{$feature}`
.note = features must begin with a `+` to enable or `-` to disable it
-codegen_llvm_error_creating_import_library =
- Error creating import library for {$lib_name}: {$error}
-
-codegen_llvm_symbol_already_defined =
- symbol `{$symbol_name}` is already defined
-
-codegen_llvm_invalid_minimum_alignment =
- invalid minimum global alignment: {$err}
-
-codegen_llvm_sanitizer_memtag_requires_mte =
- `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
-
-codegen_llvm_error_writing_def_file =
- Error writing .DEF file: {$error}
-
-codegen_llvm_error_calling_dlltool =
- Error calling dlltool '{$dlltool_path}': {$error}
-
-codegen_llvm_dlltool_fail_import_library =
- Dlltool could not create import library: {$stdout}
- {$stderr}
-
-codegen_llvm_target_feature_disable_or_enable =
- the target features {$features} must all be either enabled or disabled together
-
-codegen_llvm_missing_features =
- add the missing features in a `target_feature` attribute
-
-codegen_llvm_dynamic_linking_with_lto =
- cannot prefer dynamic linking when performing LTO
- .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
-
-codegen_llvm_parse_target_machine_config =
- failed to parse target machine config to target machine: {$error}
-
-codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
-
-codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
-
-codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
-
-codegen_llvm_write_output = could not write output to {$path}
-codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
-
-codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
-codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
-
-codegen_llvm_run_passes = failed to run LLVM passes
-codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
-
-codegen_llvm_serialize_module = failed to serialize module {$name}
-codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
codegen_llvm_write_ir = failed to write LLVM IR to {$path}
codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
-codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
-codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
-
-codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
-codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+codegen_llvm_write_output = could not write output to {$path}
+codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
-
-codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
-codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
-
-codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
-codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
-
-codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
-codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
-
-codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
-codegen_llvm_from_llvm_diag = {$message}
-
-codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
-
-codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 668d929..a575088 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -1,10 +1,12 @@
use crate::attributes;
use libc::c_uint;
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+ ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DebugInfo, OomStrategy};
-use rustc_span::symbol::sym;
use crate::debuginfo;
use crate::llvm::{self, False, True};
@@ -29,75 +31,78 @@
let i8p = llvm::LLVMPointerType(i8, 0);
let void = llvm::LLVMVoidTypeInContext(llcx);
- for method in ALLOCATOR_METHODS {
- let mut args = Vec::with_capacity(method.inputs.len());
- for ty in method.inputs.iter() {
- match *ty {
- AllocatorTy::Layout => {
- args.push(usize); // size
- args.push(usize); // align
+ if kind == AllocatorKind::Default {
+ for method in ALLOCATOR_METHODS {
+ let mut args = Vec::with_capacity(method.inputs.len());
+ for ty in method.inputs.iter() {
+ match *ty {
+ AllocatorTy::Layout => {
+ args.push(usize); // size
+ args.push(usize); // align
+ }
+ AllocatorTy::Ptr => args.push(i8p),
+ AllocatorTy::Usize => args.push(usize),
+
+ AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
- AllocatorTy::Ptr => args.push(i8p),
- AllocatorTy::Usize => args.push(usize),
-
- AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
}
- }
- let output = match method.output {
- AllocatorTy::ResultPtr => Some(i8p),
- AllocatorTy::Unit => None,
+ let output = match method.output {
+ AllocatorTy::ResultPtr => Some(i8p),
+ AllocatorTy::Unit => None,
- AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
- panic!("invalid allocator output")
+ AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+ panic!("invalid allocator output")
+ }
+ };
+ let ty = llvm::LLVMFunctionType(
+ output.unwrap_or(void),
+ args.as_ptr(),
+ args.len() as c_uint,
+ False,
+ );
+ let name = global_fn_name(method.name);
+ let llfn =
+ llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
+
+ if tcx.sess.target.default_hidden_visibility {
+ llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
- };
- let ty = llvm::LLVMFunctionType(
- output.unwrap_or(void),
- args.as_ptr(),
- args.len() as c_uint,
- False,
- );
- let name = format!("__rust_{}", method.name);
- let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
+ if tcx.sess.must_emit_unwind_tables() {
+ let uwtable = attributes::uwtable_attr(llcx);
+ attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
+ }
- if tcx.sess.target.default_hidden_visibility {
- llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+ let callee = default_fn_name(method.name);
+ let callee =
+ llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
+ llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
+
+ let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
+
+ let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
+ llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
+ let args = args
+ .iter()
+ .enumerate()
+ .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
+ .collect::<Vec<_>>();
+ let ret = llvm::LLVMRustBuildCall(
+ llbuilder,
+ ty,
+ callee,
+ args.as_ptr(),
+ args.len() as c_uint,
+ [].as_ptr(),
+ 0 as c_uint,
+ );
+ llvm::LLVMSetTailCall(ret, True);
+ if output.is_some() {
+ llvm::LLVMBuildRet(llbuilder, ret);
+ } else {
+ llvm::LLVMBuildRetVoid(llbuilder);
+ }
+ llvm::LLVMDisposeBuilder(llbuilder);
}
- if tcx.sess.must_emit_unwind_tables() {
- let uwtable = attributes::uwtable_attr(llcx);
- attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
- }
-
- let callee = kind.fn_name(method.name);
- let callee =
- llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
- llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
-
- let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
-
- let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
- llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
- let args = args
- .iter()
- .enumerate()
- .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
- .collect::<Vec<_>>();
- let ret = llvm::LLVMRustBuildCall(
- llbuilder,
- ty,
- callee,
- args.as_ptr(),
- args.len() as c_uint,
- [].as_ptr(),
- 0 as c_uint,
- );
- llvm::LLVMSetTailCall(ret, True);
- if output.is_some() {
- llvm::LLVMBuildRet(llbuilder, ret);
- } else {
- llvm::LLVMBuildRetVoid(llbuilder);
- }
- llvm::LLVMDisposeBuilder(llbuilder);
}
// rust alloc error handler
@@ -118,7 +123,7 @@
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
}
- let callee = alloc_error_handler_kind.fn_name(sym::oom);
+ let callee = alloc_error_handler_name(alloc_error_handler_kind);
let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
// -> ! DIFlagNoReturn
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
@@ -156,6 +161,14 @@
let llval = llvm::LLVMConstInt(i8, val as u64, False);
llvm::LLVMSetInitializer(ll_g, llval);
+ let name = NO_ALLOC_SHIM_IS_UNSTABLE;
+ let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
+ if tcx.sess.target.default_hidden_visibility {
+ llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
+ }
+ let llval = llvm::LLVMConstInt(i8, 0, False);
+ llvm::LLVMSetInitializer(ll_g, llval);
+
if tcx.sess.opts.debuginfo != DebugInfo::None {
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 240a9d2..21a1ac3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -163,7 +163,7 @@
counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
for (counter, region) in counter_regions {
let CodeRegion { file_name, start_line, start_col, end_line, end_col } = *region;
- let same_file = current_file_name.map_or(false, |p| p == file_name);
+ let same_file = current_file_name.is_some_and(|p| p == file_name);
if !same_file {
if current_file_name.is_some() {
current_file_id += 1;
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index e8f8c32..c24854b 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -125,8 +125,7 @@
// Thread-local variables generally don't support copy relocations.
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
- .map(|v| llvm::LLVMIsThreadLocal(v) == llvm::True)
- .unwrap_or(false);
+ .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
if is_thread_local_var {
return false;
}
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 375fdec..9aa2b2e 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -1,80 +1,258 @@
-codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
-
-codegen_ssa_version_script_write_failure = failed to write version script: {$error}
-
-codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
-
-codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
-
-codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
-
codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender
-codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
+
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
+
+codegen_ssa_archive_build_failure =
+ failed to build archive: {$error}
+
+codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+
+codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}
+codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+
+codegen_ssa_erroneous_constant = erroneous constant encountered
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+
+codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
+
+codegen_ssa_failed_to_write = failed to write {$path}: {$error}
+
codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
-codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
+ .note = an unsuffixed integer value, e.g., `1`, is expected
codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
-codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
+codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
-codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
+ .note = the attribute requires exactly one argument
-codegen_ssa_rlib_missing_format = could not find formats for rlibs
+codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
-codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
-codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
+
+codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
+
+codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
+
+codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
+
+codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
+
+codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+
+codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
+
+codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
+
+codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
+
+codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+
+codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+
+codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
+
+codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
+ .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+
+codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
+
+codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
+
+codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
+
+codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
+
+codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
+
+codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
+
+codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
+
+codegen_ssa_linker_not_found = linker `{$linker_path}` not found
+ .note = {$error}
+
+codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
-codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
+
+codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
+
+codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+
+codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
+
+codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+
+codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
+ .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
+
+codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+
+codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
+
+codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
+
+codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
+ .note = {$output}
+
+codegen_ssa_read_file = failed to read file: {$message}
+
+codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
+
+codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
+
+codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+
+codegen_ssa_rlib_missing_format = could not find formats for rlibs
+
+codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+
+codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+
+codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
+
+codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
-codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
+codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
-codegen_ssa_thorin_read_input_failure = failed to read input file
+codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
+ .note = {$output}
-codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
-codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
-
-codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
-
-codegen_ssa_thorin_parse_archive_member = failed to parse archive member
-
-codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
+ .label = cannot be applied to safe trait method
+ .label_def = not an `unsafe` function
codegen_ssa_thorin_decompress_data = failed to decompress compressed section
-codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
+codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
-codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
+codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+
+codegen_ssa_thorin_gimli_read = {$error}
+codegen_ssa_thorin_gimli_write = {$error}
+
+codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
+
+codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+
+codegen_ssa_thorin_io = {$error}
+codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
+
+codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
+
+codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+
+codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
+
+codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+
+codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset}
-codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
-
-codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
-
codegen_ssa_thorin_no_compilation_units = input object has no compilation units
codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit
-codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
+codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
-codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+
+codegen_ssa_thorin_object_read = {$error}
+codegen_ssa_thorin_object_write = {$error}
+codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
+
+codegen_ssa_thorin_parse_archive_member = failed to parse archive member
+
+codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
+
+codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
+
+codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+
+codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
+
+codegen_ssa_thorin_parse_unit = failed to parse unit
codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations
@@ -82,225 +260,47 @@
codegen_ssa_thorin_parse_unit_header = failed to parse unit header
-codegen_ssa_thorin_parse_unit = failed to parse unit
+codegen_ssa_thorin_read_input_failure = failed to read input file
-codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
-
-codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
-
-codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
-
-codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
-
-codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
+codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index
codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index
-codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
-codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
-codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
+codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
-codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
-codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
-
-codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
-
-codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
-
-codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
-
-codegen_ssa_thorin_io = {$error}
-codegen_ssa_thorin_object_read = {$error}
-codegen_ssa_thorin_object_write = {$error}
-codegen_ssa_thorin_gimli_read = {$error}
-codegen_ssa_thorin_gimli_write = {$error}
-
-codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
-
-codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
-
-codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
-
-codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
-
-codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
-
-codegen_ssa_linker_not_found = linker `{$linker_path}` not found
- .note = {$error}
+codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}`
.note = {$error}
.command_note = {$command_formatted}
-codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
-
-codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
-
-codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
-
-codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
- .note = {$output}
+codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
-codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
- .note = {$output}
-
-codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
-
-codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
-
-codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
-
-codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
-
-codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
-
-codegen_ssa_failed_to_write = failed to write {$path}: {$error}
-
codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
-codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
-
-codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
-
-codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
-
-codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-
-codegen_ssa_read_file = failed to read file: {$message}
-
-codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
-
-codegen_ssa_archive_build_failure =
- failed to build archive: {$error}
-
codegen_ssa_unknown_archive_kind =
Don't know how to build archive of type: {$kind}
-codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
-codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
- .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
-
-codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
-
-codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
-
-codegen_ssa_erroneous_constant = erroneous constant encountered
-
-codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
-
-codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+codegen_ssa_unknown_atomic_operation = unknown atomic operation
codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
-codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-codegen_ssa_unknown_atomic_operation = unknown atomic operation
+codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
-codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
-codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
+codegen_ssa_version_script_write_failure = failed to write version script: {$error}
-codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
-
-codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
-
-codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
-
-codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
-codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
-
-codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
-
-codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
-
-codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
-
-codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
-
-codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
-
-codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
-
-codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
-
-codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
-
-codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
-
-codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
-
-codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
-
-codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
- .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
-
-codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
- .note = the attribute requires exactly one argument
-
-codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
- .note = an unsuffixed integer value, e.g., `1`, is expected
-
-codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
- .label = cannot be applied to safe trait method
- .label_def = not an `unsafe` function
+codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 1e57f42..cd56f85 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -144,7 +144,7 @@
cmd,
sess,
target_cpu,
- hinted_static: false,
+ hinted_static: None,
is_ld: cc == Cc::No,
is_gnu: flavor.is_gnu(),
}) as Box<dyn Linker>,
@@ -214,7 +214,7 @@
cmd: Command,
sess: &'a Session,
target_cpu: &'a str,
- hinted_static: bool, // Keeps track of the current hinting mode.
+ hinted_static: Option<bool>, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
is_gnu: bool,
@@ -275,9 +275,9 @@
if !self.takes_hints() {
return;
}
- if !self.hinted_static {
+ if self.hinted_static != Some(true) {
self.linker_arg("-Bstatic");
- self.hinted_static = true;
+ self.hinted_static = Some(true);
}
}
@@ -285,9 +285,9 @@
if !self.takes_hints() {
return;
}
- if self.hinted_static {
+ if self.hinted_static != Some(false) {
self.linker_arg("-Bdynamic");
- self.hinted_static = false;
+ self.hinted_static = Some(false);
}
}
@@ -1484,25 +1484,25 @@
pub struct AixLinker<'a> {
cmd: Command,
sess: &'a Session,
- hinted_static: bool,
+ hinted_static: Option<bool>,
}
impl<'a> AixLinker<'a> {
pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
- AixLinker { cmd: cmd, sess: sess, hinted_static: false }
+ AixLinker { cmd: cmd, sess: sess, hinted_static: None }
}
fn hint_static(&mut self) {
- if !self.hinted_static {
+ if self.hinted_static != Some(true) {
self.cmd.arg("-bstatic");
- self.hinted_static = true;
+ self.hinted_static = Some(true);
}
}
fn hint_dynamic(&mut self) {
- if self.hinted_static {
+ if self.hinted_static != Some(false) {
self.cmd.arg("-bdynamic");
- self.hinted_static = false;
+ self.hinted_static = Some(false);
}
}
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8bf8477..ad27b85 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -188,6 +188,11 @@
};
let mut file = write::Object::new(binary_format, architecture, endianness);
+ if sess.target.is_like_osx {
+ if let Some(build_version) = macho_object_build_version_for_target(&sess.target) {
+ file.set_macho_build_version(build_version)
+ }
+ }
let e_flags = match architecture {
Architecture::Mips => {
let arch = match sess.target.options.cpu.as_ref() {
@@ -258,6 +263,33 @@
Some(file)
}
+/// Apple's LD, when linking for Mac Catalyst, requires object files to
+/// contain information about what they were built for (LC_BUILD_VERSION):
+/// the platform (macOS/watchOS etc), minimum OS version, and SDK version.
+/// This returns a `MachOBuildVersion` if necessary for the target.
+fn macho_object_build_version_for_target(
+ target: &Target,
+) -> Option<object::write::MachOBuildVersion> {
+ if !target.llvm_target.ends_with("-macabi") {
+ return None;
+ }
+ /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
+ /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
+ fn pack_version((major, minor): (u32, u32)) -> u32 {
+ (major << 16) | (minor << 8)
+ }
+
+ let platform = object::macho::PLATFORM_MACCATALYST;
+ let min_os = (14, 0);
+ let sdk = (16, 2);
+
+ let mut build_version = object::write::MachOBuildVersion::default();
+ build_version.platform = platform;
+ build_version.minos = pack_version(min_os);
+ build_version.sdk = pack_version(sdk);
+ Some(build_version)
+}
+
pub enum MetadataPosition {
First,
Last,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 14460ef..a8b6030 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -2,7 +2,7 @@
use std::collections::hash_map::Entry::*;
-use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
+use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
@@ -241,6 +241,17 @@
used: false,
},
));
+
+ let exported_symbol =
+ ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE));
+ symbols.push((
+ exported_symbol,
+ SymbolExportInfo {
+ level: SymbolExportLevel::Rust,
+ kind: SymbolExportKind::Data,
+ used: false,
+ },
+ ))
}
if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 569599f..8350748 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -84,7 +84,7 @@
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
fx: &'mir FunctionCx<'a, 'tcx, Bx>,
- dominators: Dominators<mir::BasicBlock>,
+ dominators: &'mir Dominators<mir::BasicBlock>,
locals: IndexVec<mir::Local, LocalKind>,
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a832999..3f0b64b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1031,7 +1031,7 @@
});
let needs_location =
- instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx()));
+ instance.is_some_and(|i| i.def.requires_caller_location(self.cx.tcx()));
if needs_location {
let mir_args = if let Some(num_untupled) = num_untupled {
first_args.len() + num_untupled
@@ -1256,7 +1256,7 @@
MergingSucc::False
}
- mir::TerminatorKind::Drop { place, target, unwind } => {
+ mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ())
}
@@ -1450,11 +1450,7 @@
) -> OperandRef<'tcx, Bx::Value> {
let tcx = bx.tcx();
- let mut span_to_caller_location = |mut span: Span| {
- // Remove `Inlined` marks as they pollute `expansion_cause`.
- while span.is_inlined() {
- span.remove_mark();
- }
+ let mut span_to_caller_location = |span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = tcx.const_caller_location((
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index f6751df..7d56cf0 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -1,10 +1,36 @@
-const_eval_unstable_in_stable =
- const-stable function cannot use `#[feature({$gate})]`
- .unstable_sugg = if it is not part of the public API, make this function unstably const
- .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
+const_eval_interior_mutability_borrow =
+ cannot borrow here, since the borrowed element may contain interior mutability
-const_eval_thread_local_access =
- thread-local statics cannot be accessed at compile-time
+const_eval_interior_mutable_data_refer =
+ {$kind}s cannot refer to interior mutable data
+ .label = this borrow of an interior mutable value may end up in the final value
+ .help = to fix this, the value can be extracted to a separate `static` item and then referenced
+ .teach_note =
+ A constant containing interior mutable data behind a reference can allow you to modify that data.
+ This would make multiple uses of a constant to be able to see different values and allow circumventing
+ the `Send` and `Sync` requirements for shared mutable data, which is unsound.
+
+const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
+
+const_eval_mut_deref =
+ mutation through a reference is not allowed in {$kind}s
+
+const_eval_non_const_fmt_macro_call =
+ cannot call non-const formatting macro in {$kind}s
+
+const_eval_non_const_fn_call =
+ cannot call non-const fn `{$def_path_str}` in {$kind}s
+
+const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
+
+const_eval_raw_ptr_comparison =
+ pointers cannot be reliably compared during const eval
+ .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+
+const_eval_raw_ptr_to_int =
+ pointers cannot be cast to integers during const eval
+ .note = at compile-time, pointers do not have an integer value
+ .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
const_eval_static_access =
{$kind}s cannot refer to statics
@@ -12,29 +38,23 @@
.teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
.teach_help = To fix this, the value can be extracted to a `const` and then used.
-const_eval_raw_ptr_to_int =
- pointers cannot be cast to integers during const eval
- .note = at compile-time, pointers do not have an integer value
- .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-
-const_eval_raw_ptr_comparison =
- pointers cannot be reliably compared during const eval
- .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
-
-const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
-
-const_eval_mut_deref =
- mutation through a reference is not allowed in {$kind}s
+const_eval_thread_local_access =
+ thread-local statics cannot be accessed at compile-time
const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
-const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
-
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
-const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
+const_eval_unallowed_heap_allocations =
+ allocations are not allowed in {$kind}s
+ .label = allocation not allowed in {$kind}s
+ .teach_note =
+ The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+
+const_eval_unallowed_inline_asm =
+ inline assembly is not allowed in {$kind}s
const_eval_unallowed_mutable_refs =
mutable references are not allowed in the final value of {$kind}s
@@ -60,32 +80,12 @@
If you really want global mutable state, try using static mut or a global UnsafeCell.
-const_eval_non_const_fmt_macro_call =
- cannot call non-const formatting macro in {$kind}s
-
-const_eval_non_const_fn_call =
- cannot call non-const fn `{$def_path_str}` in {$kind}s
-
const_eval_unallowed_op_in_const_context =
{$msg}
-const_eval_unallowed_heap_allocations =
- allocations are not allowed in {$kind}s
- .label = allocation not allowed in {$kind}s
- .teach_note =
- The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
-const_eval_unallowed_inline_asm =
- inline assembly is not allowed in {$kind}s
-
-const_eval_interior_mutable_data_refer =
- {$kind}s cannot refer to interior mutable data
- .label = this borrow of an interior mutable value may end up in the final value
- .help = to fix this, the value can be extracted to a separate `static` item and then referenced
- .teach_note =
- A constant containing interior mutable data behind a reference can allow you to modify that data.
- This would make multiple uses of a constant to be able to see different values and allow circumventing
- the `Send` and `Sync` requirements for shared mutable data, which is unsound.
-
-const_eval_interior_mutability_borrow =
- cannot borrow here, since the borrowed element may contain interior mutability
+const_eval_unstable_in_stable =
+ const-stable function cannot use `#[feature({$gate})]`
+ .unstable_sugg = if it is not part of the public API, make this function unstably const
+ .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 040eba1..7e94578 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -949,7 +949,20 @@
// This deliberately does *not* honor `requires_caller_location` since it is used for much
// more than just panics.
for frame in stack.iter().rev() {
- let span = frame.current_span();
+ let span = match frame.loc {
+ Left(loc) => {
+ // If the stacktrace passes through MIR-inlined source scopes, add them.
+ let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
+ let mut scope_data = &frame.body.source_scopes[scope];
+ while let Some((instance, call_span)) = scope_data.inlined {
+ frames.push(FrameInfo { span, instance });
+ span = call_span;
+ scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
+ }
+ span
+ }
+ Right(span) => span,
+ };
frames.push(FrameInfo { span, instance: frame.instance });
}
trace!("generate stacktrace: {:#?}", frames);
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 3701eb9..df5b581 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -111,11 +111,7 @@
location
}
- pub(crate) fn location_triple_for_span(&self, mut span: Span) -> (Symbol, u32, u32) {
- // Remove `Inlined` marks as they pollute `expansion_cause`.
- while span.is_inlined() {
- span.remove_mark();
- }
+ pub(crate) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
(
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index df38792..586e8f0 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -114,7 +114,7 @@
}
}
- Drop { place, target, unwind } => {
+ Drop { place, target, unwind, replace: _ } => {
let frame = self.frame();
let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 696c451..138bc3e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -944,7 +944,7 @@
tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate)
};
let feature_gate_declared = gate_declared(gate);
- let implied_gate_declared = implied_by.map(gate_declared).unwrap_or(false);
+ let implied_gate_declared = implied_by.is_some_and(gate_declared);
if !feature_gate_declared && !implied_gate_declared {
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
@@ -971,7 +971,7 @@
// have no `rustc_const_stable` attributes to be const-unstable as well. This
// should be fixed later.
let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
- && tcx.lookup_stability(callee).map_or(false, |s| s.is_unstable());
+ && tcx.lookup_stability(callee).is_some_and(|s| s.is_unstable());
if callee_is_unstable_unmarked {
trace!("callee_is_unstable_unmarked");
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 0e45019..8ebfee8 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -139,5 +139,5 @@
return false;
}
- tcx.lookup_const_stability(parent.owner).map_or(false, |stab| stab.is_const_stable())
+ tcx.lookup_const_stability(parent.owner).is_some_and(|stab| stab.is_const_stable())
}
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index f5f3d5d..d6a2ffb 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -3,8 +3,8 @@
//! FIXME: Move this to a more general place. The utility of this extends to
//! other areas of the compiler as well.
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::traits::{DefiningAnchor, ObligationCause};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_trait_selection::traits::ObligationCtxt;
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 594ed1a..a5db14d 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -26,7 +26,7 @@
struct PreorderIndex {}
}
-pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
+pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
// compute the post order index (rank) for each node
let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
@@ -244,7 +244,10 @@
let start_node = graph.start_node();
immediate_dominators[start_node] = None;
- Dominators { start_node, post_order_rank, immediate_dominators }
+
+ let time = compute_access_time(start_node, &immediate_dominators);
+
+ Dominators { start_node, post_order_rank, immediate_dominators, time }
}
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -316,6 +319,7 @@
// possible to get its full list of dominators by looking up the dominator
// of each dominator. (See the `impl Iterator for Iter` definition).
immediate_dominators: IndexVec<N, Option<N>>,
+ time: IndexVec<N, Time>,
}
impl<Node: Idx> Dominators<Node> {
@@ -333,12 +337,7 @@
/// See the `impl Iterator for Iter` definition to understand how this works.
pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
assert!(self.is_reachable(node), "node {node:?} is not reachable");
- Iter { dominators: self, node: Some(node) }
- }
-
- pub fn dominates(&self, dom: Node, node: Node) -> bool {
- // FIXME -- could be optimized by using post-order-rank
- self.dominators(node).any(|n| n == dom)
+ Iter { dom_tree: self, node: Some(node) }
}
/// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
@@ -348,10 +347,22 @@
pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs])
}
+
+ /// Returns true if `a` dominates `b`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `b` is unreachable.
+ pub fn dominates(&self, a: Node, b: Node) -> bool {
+ let a = self.time[a];
+ let b = self.time[b];
+ assert!(b.start != 0, "node {b:?} is not reachable");
+ a.start <= b.start && b.finish <= a.finish
+ }
}
pub struct Iter<'dom, Node: Idx> {
- dominators: &'dom Dominators<Node>,
+ dom_tree: &'dom Dominators<Node>,
node: Option<Node>,
}
@@ -360,10 +371,74 @@
fn next(&mut self) -> Option<Self::Item> {
if let Some(node) = self.node {
- self.node = self.dominators.immediate_dominator(node);
+ self.node = self.dom_tree.immediate_dominator(node);
Some(node)
} else {
None
}
}
}
+
+/// Describes the number of vertices discovered at the time when processing of a particular vertex
+/// started and when it finished. Both values are zero for unreachable vertices.
+#[derive(Copy, Clone, Default, Debug)]
+struct Time {
+ start: u32,
+ finish: u32,
+}
+
+fn compute_access_time<N: Idx>(
+ start_node: N,
+ immediate_dominators: &IndexSlice<N, Option<N>>,
+) -> IndexVec<N, Time> {
+ // Transpose the dominator tree edges, so that child nodes of vertex v are stored in
+ // node[edges[v].start..edges[v].end].
+ let mut edges: IndexVec<N, std::ops::Range<u32>> =
+ IndexVec::from_elem(0..0, immediate_dominators);
+ for &idom in immediate_dominators.iter() {
+ if let Some(idom) = idom {
+ edges[idom].end += 1;
+ }
+ }
+ let mut m = 0;
+ for e in edges.iter_mut() {
+ m += e.end;
+ e.start = m;
+ e.end = m;
+ }
+ let mut node = IndexVec::from_elem_n(Idx::new(0), m.try_into().unwrap());
+ for (i, &idom) in immediate_dominators.iter_enumerated() {
+ if let Some(idom) = idom {
+ edges[idom].start -= 1;
+ node[edges[idom].start] = i;
+ }
+ }
+
+ // Perform a depth-first search of the dominator tree. Record the number of vertices discovered
+ // when vertex v is discovered first as time[v].start, and when its processing is finished as
+ // time[v].finish.
+ let mut time: IndexVec<N, Time> = IndexVec::from_elem(Time::default(), immediate_dominators);
+ let mut stack = Vec::new();
+
+ let mut discovered = 1;
+ stack.push(start_node);
+ time[start_node].start = discovered;
+
+ while let Some(&i) = stack.last() {
+ let e = &mut edges[i];
+ if e.start == e.end {
+ // Finish processing vertex i.
+ time[i].finish = discovered;
+ stack.pop();
+ } else {
+ let j = node[e.start];
+ e.start += 1;
+ // Start processing vertex j.
+ discovered += 1;
+ time[j].start = discovered;
+ stack.push(j);
+ }
+ }
+
+ time
+}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 5b9b0e1..859e384 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -102,21 +102,27 @@
pub use ena::undo_log;
pub use ena::unify;
-pub struct OnDrop<F: Fn()>(pub F);
+/// Returns a structure that calls `f` when dropped.
+pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
+ OnDrop(Some(f))
+}
-impl<F: Fn()> OnDrop<F> {
- /// Forgets the function which prevents it from running.
- /// Ensure that the function owns no memory, otherwise it will be leaked.
+pub struct OnDrop<F: FnOnce()>(Option<F>);
+
+impl<F: FnOnce()> OnDrop<F> {
+ /// Disables on-drop call.
#[inline]
- pub fn disable(self) {
- std::mem::forget(self);
+ pub fn disable(mut self) {
+ self.0.take();
}
}
-impl<F: Fn()> Drop for OnDrop<F> {
+impl<F: FnOnce()> Drop for OnDrop<F> {
#[inline]
fn drop(&mut self) {
- (self.0)();
+ if let Some(f) = self.0.take() {
+ f();
+ }
}
}
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 27a869e..a479086 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -366,7 +366,7 @@
&& self
.error_cache
.get(&obligation_tree_id)
- .map_or(false, |errors| errors.contains(v.key()));
+ .is_some_and(|errors| errors.contains(v.key()));
if already_failed {
Err(())
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index 1eb5378..520871a 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -7,8 +7,8 @@
};
use crate::{
+ defer,
owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
- OnDrop,
};
#[test]
@@ -66,7 +66,7 @@
fn drop_drops() {
let flag = Arc::new(AtomicBool::new(false));
let flag_prime = Arc::clone(&flag);
- let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
+ let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
let slice = slice_owned(d, |_| &[]);
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index f19b1ff..22b4ec6 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,19 +1,19 @@
-driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
-driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
-
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_version = rustc {$version} running on {$triple}
driver_impl_rlink_empty_version_number = The input does not contain version number
driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
-driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-
driver_impl_rlink_no_a_file = rlink must be a file
-driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
-driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
-driver_impl_ice_version = rustc {$version} running on {$triple}
-driver_impl_ice_flags = compiler flags: {$flags}
-driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
+
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
+
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 6c204b8..40aa69e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1315,7 +1315,7 @@
}
// If backtraces are enabled, also print the query stack
- let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
+ let backtrace = env::var_os("RUST_BACKTRACE").is_some_and(|x| &x != "0");
let num_frames = if backtrace { None } else { Some(2) };
diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl
index dde1d6c..3370973 100644
--- a/compiler/rustc_errors/messages.ftl
+++ b/compiler/rustc_errors/messages.ftl
@@ -1,19 +1,19 @@
-errors_target_invalid_address_space =
- invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_invalid_bits =
- invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_missing_alignment =
- missing alignment for `{$cause}` in "data-layout"
-
-errors_target_invalid_alignment =
- invalid alignment for `{$cause}` in "data-layout": {$err}
-
errors_target_inconsistent_architecture =
inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
errors_target_inconsistent_pointer_width =
inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
+errors_target_invalid_address_space =
+ invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
+
+errors_target_invalid_alignment =
+ invalid alignment for `{$cause}` in "data-layout": {$err}
+
+errors_target_invalid_bits =
+ invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
+
errors_target_invalid_bits_size = {$err}
+
+errors_target_missing_alignment =
+ missing alignment for `{$cause}` in "data-layout"
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 3e38d6a..e8cd7ea 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -285,15 +285,11 @@
format!(
"help: {}{}: `{}`",
&msg,
- if self
- .source_map()
- .map(|sm| is_case_difference(
- sm,
- substitution,
- sugg.substitutions[0].parts[0].span,
- ))
- .unwrap_or(false)
- {
+ if self.source_map().is_some_and(|sm| is_case_difference(
+ sm,
+ substitution,
+ sugg.substitutions[0].parts[0].span,
+ )) {
" (notice the capitalization)"
} else {
""
@@ -336,7 +332,7 @@
// Skip past non-macro entries, just in case there
// are some which do actually involve macros.
- ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
+ ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)),
}
@@ -407,7 +403,7 @@
continue;
}
- if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) {
+ if always_backtrace {
new_labels.push((
trace.def_site,
format!(
@@ -446,7 +442,6 @@
"this derive macro expansion".into()
}
ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
- ExpnKind::Inlined => "this inlined function call".into(),
ExpnKind::Root => "the crate root".into(),
ExpnKind::AstPass(kind) => kind.descr().into(),
ExpnKind::Desugaring(kind) => {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 074fbb1..3dec0d9 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1437,7 +1437,7 @@
}
fn treat_err_as_bug(&self) -> bool {
- self.flags.treat_err_as_bug.map_or(false, |c| {
+ self.flags.treat_err_as_bug.is_some_and(|c| {
self.err_count() + self.lint_err_count + self.delayed_bug_count() >= c.get()
})
}
@@ -1603,7 +1603,7 @@
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
// incrementing `err_count` by one, so we need to +1 the comparing.
// FIXME: Would be nice to increment err_count in a more coherent way.
- if self.flags.treat_err_as_bug.map_or(false, |c| {
+ if self.flags.treat_err_as_bug.is_some_and(|c| {
self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
}) {
// FIXME: don't abort here if report_delayed_bugs is off
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 70d2718..6c7e682 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -1,56 +1,8 @@
-expand_explain_doc_comment_outer =
- outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
-
-expand_explain_doc_comment_inner =
- inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
-
-expand_expr_repeat_no_syntax_vars =
- attempted to repeat an expression containing no syntax variables matched as repeating at this depth
-
-expand_must_repeat_once =
- this must repeat at least once
-
-expand_count_repetition_misplaced =
- `count` can not be placed inside the inner-most repetition
-
-expand_meta_var_expr_unrecognized_var =
- variable `{$key}` is not recognized in meta-variable expression
-
-expand_var_still_repeating =
- variable '{$ident}' is still repeating at this depth
-
-expand_meta_var_dif_seq_matchers = {$msg}
-
-expand_macro_const_stability =
- macros cannot have const stability attributes
- .label = invalid const stability attribute
- .label2 = const stability attribute affects this macro
-
-expand_macro_body_stability =
- macros cannot have body stability attributes
- .label = invalid body stability attribute
- .label2 = body stability attribute affects this macro
-
-expand_resolve_relative_path =
- cannot resolve relative path in non-file source `{$path}`
-
-expand_attr_no_arguments =
- attribute must have either one or two arguments
-
-expand_not_a_meta_item =
- not a meta item
-
-expand_only_one_word =
- must only be one word
-
-expand_cannot_be_name_of_macro =
- `{$trait_ident}` cannot be a name of {$macro_type} macro
-
expand_arg_not_attributes =
second argument must be `attributes`
-expand_attributes_wrong_form =
- attribute must be of form: `attributes(foo, bar)`
+expand_attr_no_arguments =
+ attribute must have either one or two arguments
expand_attribute_meta_item =
attribute must be a meta item, not a literal
@@ -58,51 +10,44 @@
expand_attribute_single_word =
attribute must only be a single word
-expand_helper_attribute_name_invalid =
- `{$name}` cannot be a name of derive helper attribute
+expand_attributes_wrong_form =
+ attribute must be of form: `attributes(foo, bar)`
+
+expand_cannot_be_name_of_macro =
+ `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_count_repetition_misplaced =
+ `count` can not be placed inside the inner-most repetition
+
+expand_duplicate_matcher_binding = duplicate matcher binding
+ .label = duplicate binding
+ .label2 = previous binding
expand_expected_comma_in_list =
expected token: `,`
-expand_only_one_argument =
- {$name} takes 1 argument
+expand_explain_doc_comment_inner =
+ inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
-expand_takes_no_arguments =
- {$name} takes no arguments
+expand_explain_doc_comment_outer =
+ outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
+
+expand_expr_repeat_no_syntax_vars =
+ attempted to repeat an expression containing no syntax variables matched as repeating at this depth
expand_feature_included_in_edition =
the feature `{$feature}` is included in the Rust {$edition} edition
+expand_feature_not_allowed =
+ the feature `{$name}` is not in the list of allowed features
+
expand_feature_removed =
feature has been removed
.label = feature has been removed
.reason = {$reason}
-expand_feature_not_allowed =
- the feature `{$name}` is not in the list of allowed features
-
-expand_recursion_limit_reached =
- recursion limit reached while expanding `{$descr}`
- .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-
-expand_malformed_feature_attribute =
- malformed `feature` attribute input
- .expected = expected just one word
-
-expand_remove_expr_not_supported =
- removing an expression is not supported in this position
-
-expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
-expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
-expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
-expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
-expand_invalid_cfg_expected_syntax = expected syntax is
-
-expand_wrong_fragment_kind =
- non-{$kind} macro in {$kind} position: {$name}
-
-expand_unsupported_key_value =
- key-value macro attributes are not supported
+expand_helper_attribute_name_invalid =
+ `{$name}` cannot be a name of derive helper attribute
expand_incomplete_parse =
macro expansion ignores token `{$token}` and any following
@@ -110,33 +55,88 @@
.note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
.suggestion_add_semi = you might be missing a semicolon here
-expand_remove_node_not_supported =
- removing {$descr} is not supported in this position
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_macro_body_stability =
+ macros cannot have body stability attributes
+ .label = invalid body stability attribute
+ .label2 = body stability attribute affects this macro
+
+expand_macro_const_stability =
+ macros cannot have const stability attributes
+ .label = invalid const stability attribute
+ .label2 = const stability attribute affects this macro
+
+expand_malformed_feature_attribute =
+ malformed `feature` attribute input
+ .expected = expected just one word
+
+expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_meta_var_expr_unrecognized_var =
+ variable `{$key}` is not recognized in meta-variable expression
expand_module_circular =
circular modules: {$modules}
-expand_module_in_block =
- cannot declare a non-inline module inside a block unless it has a path attribute
- .note = maybe `use` the module `{$name}` instead of redeclaring it
-
expand_module_file_not_found =
file not found for module `{$name}`
.help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+expand_module_in_block =
+ cannot declare a non-inline module inside a block unless it has a path attribute
+ .note = maybe `use` the module `{$name}` instead of redeclaring it
+
expand_module_multiple_candidates =
file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
.help = delete or rename one of them to remove the ambiguity
-expand_trace_macro = trace_macro
+expand_must_repeat_once =
+ this must repeat at least once
+
+expand_not_a_meta_item =
+ not a meta item
+
+expand_only_one_argument =
+ {$name} takes 1 argument
+
+expand_only_one_word =
+ must only be one word
+
+expand_proc_macro_derive_tokens =
+ proc-macro derive produced unparsable tokens
expand_proc_macro_panicked =
proc macro panicked
.help = message: {$message}
-expand_proc_macro_derive_tokens =
- proc-macro derive produced unparsable tokens
+expand_recursion_limit_reached =
+ recursion limit reached while expanding `{$descr}`
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-expand_duplicate_matcher_binding = duplicate matcher binding
- .label = duplicate binding
- .label2 = previous binding
+expand_remove_expr_not_supported =
+ removing an expression is not supported in this position
+
+expand_remove_node_not_supported =
+ removing {$descr} is not supported in this position
+
+expand_resolve_relative_path =
+ cannot resolve relative path in non-file source `{$path}`
+
+expand_takes_no_arguments =
+ {$name} takes no arguments
+
+expand_trace_macro = trace_macro
+
+expand_unsupported_key_value =
+ key-value macro attributes are not supported
+
+expand_var_still_repeating =
+ variable '{$ident}' is still repeating at this depth
+
+expand_wrong_fragment_kind =
+ non-{$kind} macro in {$kind} position: {$name}
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index fd72174..4671adc 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -780,7 +780,7 @@
let allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe);
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
.and_then(|macro_export| macro_export.meta_item_list())
- .map_or(false, |l| attr::list_contains_name(&l, sym::local_inner_macros));
+ .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo);
tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
@@ -1449,7 +1449,7 @@
&& version
.next()
.and_then(|c| c.parse::<u32>().ok())
- .map_or(false, |v| v < 6)
+ .is_some_and(|v| v < 6)
};
if crate_matches {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 5d369a1..ce0093c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1599,7 +1599,7 @@
cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
break;
} else if attr_pos.is_none()
- && !name.map_or(false, rustc_feature::is_builtin_attr_name)
+ && !name.is_some_and(rustc_feature::is_builtin_attr_name)
{
attr_pos = Some(pos); // a non-cfg attr found, still may find a cfg attr
}
@@ -1647,7 +1647,7 @@
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
span = Some(current_span);
- if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
+ if attrs.peek().is_some_and(|next_attr| next_attr.doc_str().is_some()) {
continue;
}
@@ -1950,6 +1950,6 @@
}
fn proc_macro_hygiene(&self) -> bool {
- self.features.map_or(false, |features| features.proc_macro_hygiene)
+ self.features.is_some_and(|features| features.proc_macro_hygiene)
}
}
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 61cfbf5..06f4a0b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -861,11 +861,11 @@
/// Whether this builtin attribute is only used in the local crate.
/// If so, it is not encoded in the crate metadata.
pub fn is_builtin_only_local(name: Symbol) -> bool {
- BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
+ BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.only_local)
}
pub fn is_valid_for_get_attr(name: Symbol) -> bool {
- BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| match attr.duplicates {
+ BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates {
WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
| FutureWarnPreceding => true,
DuplicatesOk | WarnFollowingWordOnly => false,
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 3ce16e1..beb6307 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -84,14 +84,13 @@
pub fn from_environment(krate: Option<&str>) -> Self {
// `true` if this is a feature-staged build, i.e., on the beta or stable channel.
let disable_unstable_features =
- option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
+ option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some_and(|s| s != "0");
// Returns whether `krate` should be counted as unstable
- let is_unstable_crate = |var: &str| {
- krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
- };
+ let is_unstable_crate =
+ |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
// `true` if we should enable unstable features for bootstrapping.
- let bootstrap = std::env::var("RUSTC_BOOTSTRAP")
- .map_or(false, |var| var == "1" || is_unstable_crate(&var));
+ let bootstrap =
+ std::env::var("RUSTC_BOOTSTRAP").is_ok_and(|var| var == "1" || is_unstable_crate(&var));
match (disable_unstable_features, bootstrap) {
(_, true) => UnstableFeatures::Cheat,
(true, _) => UnstableFeatures::Disallow,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 932f039..e844731 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -787,7 +787,7 @@
impl<'hir> WhereBoundPredicate<'hir> {
/// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
- self.bounded_ty.as_generic_param().map_or(false, |(def_id, _)| def_id == param_def_id)
+ self.bounded_ty.as_generic_param().is_some_and(|(def_id, _)| def_id == param_def_id)
}
}
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5e5c984..02d1dfc 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,17 +1,103 @@
-hir_analysis_unrecognized_atomic_operation =
- unrecognized atomic operation function: `{$op}`
- .label = unrecognized atomic operation
+hir_analysis_ambiguous_lifetime_bound =
+ ambiguous lifetime bound, explicit lifetime bound required
-hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
- intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
- .label = expected {$expected} {$descr} {$expected ->
- [one] parameter
- *[other] parameters
- }
+hir_analysis_assoc_type_binding_not_allowed =
+ associated type bindings are not allowed here
+ .label = associated type not allowed here
-hir_analysis_unrecognized_intrinsic_function =
- unrecognized intrinsic function: `{$name}`
- .label = unrecognized intrinsic
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+ .suggestion = use a fully qualified path with inferred lifetimes
+
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+
+hir_analysis_async_trait_impl_should_be_async =
+ method `{$method_name}` should be async because the method from the trait is async
+ .trait_item_label = required because the trait method is async
+
+hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+ .label = deref recursion limit reached
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+ cannot capture late-bound const parameter in a constant
+ .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+ cannot capture late-bound type parameter in a constant
+ .label = parameter defined here
+
+hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+
+hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
+ .label = `for<...>` is here
+
+hir_analysis_const_bound_for_non_const_trait =
+ ~const can only be applied to `#[const_trait]` traits
+
+hir_analysis_const_impl_for_non_const_trait =
+ const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
+ .suggestion = mark `{$trait_name}` as const
+ .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ .adding = adding a non-const method body in the future would be a breaking change
+
+hir_analysis_const_param_ty_impl_on_non_adt =
+ the trait `ConstParamTy` may not be implemented for this type
+ .label = type is not a structure or enumeration
+
+hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+
+hir_analysis_copy_impl_on_non_adt =
+ the trait `Copy` cannot be implemented for this type
+ .label = type is not a structure or enumeration
+
+hir_analysis_copy_impl_on_type_with_dtor =
+ the trait `Copy` cannot be implemented for this type; the type has a destructor
+ .label = `Copy` not allowed on types with destructors
+
+hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+
+hir_analysis_drop_impl_on_wrong_item =
+ the `Drop` trait may only be implemented for local structs, enums, and unions
+ .label = must be a struct, enum, or union in the current crate
+
+hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+
+hir_analysis_empty_specialization = specialization impl does not specialize any associated items
+ .note = impl is a specialization of this impl
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+ .label = overflowed on value after {$discr}
+ .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+hir_analysis_field_already_declared =
+ field `{$field_name}` is already declared
+ .label = field already declared
+ .previous_decl_label = `{$field_name}` first declared here
+
+hir_analysis_function_not_found_in_trait = function not found in this trait
+
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+ .note = required by this annotation
+
+hir_analysis_functions_names_duplicated = functions names are duplicated
+ .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+
+hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+ .label = cannot specialize default item `{$ident}`
+ .ok_label = parent `impl` is here
+ .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
+
+hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+ .note = parent implementation is in crate `{$cname}`
+
+hir_analysis_invalid_union_field =
+ field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+ .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+
+hir_analysis_invalid_union_field_sugg =
+ wrap the field type in `ManuallyDrop<...>`
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
@@ -20,58 +106,39 @@
.where_label = this `where` clause might not match the one in the trait
.bounds_label = this bound might be missing in the impl
-hir_analysis_async_trait_impl_should_be_async =
- method `{$method_name}` should be async because the method from the trait is async
- .trait_item_label = required because the trait method is async
+hir_analysis_linkage_type =
+ invalid type for variable with `#[linkage]` attribute
-hir_analysis_drop_impl_on_wrong_item =
- the `Drop` trait may only be implemented for local structs, enums, and unions
- .label = must be a struct, enum, or union in the current crate
+hir_analysis_main_function_async = `main` function is not allowed to be `async`
+ .label = `main` function is not allowed to be `async`
-hir_analysis_field_already_declared =
- field `{$field_name}` is already declared
- .label = field already declared
- .previous_decl_label = `{$field_name}` first declared here
+hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
+ .label = `main` cannot have generic parameters
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
-hir_analysis_const_param_ty_impl_on_non_adt =
- the trait `ConstParamTy` may not be implemented for this type
- .label = type is not a structure or enumeration
-
-hir_analysis_ambiguous_lifetime_bound =
- ambiguous lifetime bound, explicit lifetime bound required
-
-hir_analysis_assoc_type_binding_not_allowed =
- associated type bindings are not allowed here
- .label = associated type not allowed here
-
-hir_analysis_parenthesized_fn_trait_expansion =
- parenthesized trait syntax expands to `{$expanded_type}`
-
-hir_analysis_typeof_reserved_keyword_used =
- `typeof` is a reserved keyword but unimplemented
- .suggestion = consider replacing `typeof(...)` with an actual type
- .label = reserved keyword
-
-hir_analysis_value_of_associated_struct_already_specified =
- the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
- .label = re-bound here
- .previous_bound_label = `{$item_name}` bound here first
-
-hir_analysis_unconstrained_opaque_type = unconstrained opaque type
- .note = `{$name}` must be used in combination with a concrete type within the same {$what}
+hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
hir_analysis_manual_implementation =
manual implementations of `{$trait_name}` are experimental
.label = manual implementations of `{$trait_name}` are experimental
.help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
-hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
+ .label = missing one of `{$missing_items_msg}` in implementation
+ .note = required because of this annotation
-hir_analysis_trait_object_declared_with_no_traits =
- at least one trait is required for an object type
- .alias_span = this alias does not contain a trait
+hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+
+hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
+ .label = missing `{$missing_items_msg}` in implementation
+
+hir_analysis_missing_trait_item_label = `{$item}` from trait
+
+hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+
+hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
+ .note = default implementation of `{$missing_item_name}` is unstable
+ .some_note = use of unstable library feature '{$feature}': {$r}
+ .none_note = use of unstable library feature '{$feature}'
hir_analysis_missing_type_params =
the type {$parameterCount ->
@@ -95,98 +162,35 @@
} to {$parameters}
.note = because of the default `Self` reference, type parameters must be specified on object types
-hir_analysis_copy_impl_on_type_with_dtor =
- the trait `Copy` cannot be implemented for this type; the type has a destructor
- .label = `Copy` not allowed on types with destructors
-
hir_analysis_multiple_relaxed_default_bounds =
type parameter has more than one relaxed default bound, only one is supported
-hir_analysis_copy_impl_on_non_adt =
- the trait `Copy` cannot be implemented for this type
- .label = type is not a structure or enumeration
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
-hir_analysis_const_impl_for_non_const_trait =
- const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
- .suggestion = mark `{$trait_name}` as const
- .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
- .adding = adding a non-const method body in the future would be a breaking change
+hir_analysis_must_implement_not_function = not a function
-hir_analysis_const_bound_for_non_const_trait =
- ~const can only be applied to `#[const_trait]` traits
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
-hir_analysis_self_in_impl_self =
- `Self` is not valid in the self type of an impl block
- .note = replace `Self` with a different type
+hir_analysis_must_implement_not_function_span_note = required by this annotation
-hir_analysis_linkage_type =
- invalid type for variable with `#[linkage]` attribute
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
- .label = deref recursion limit reached
- .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+ .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
-hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
- .label = `main` cannot have a `where` clause
-
-hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
- .suggestion = remove this annotation
-
-hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
- .label = `start` is not allowed to be `#[track_caller]`
-
-hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
- .label = `start` is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_async = `start` is not allowed to be `async`
- .label = `start` is not allowed to be `async`
-
-hir_analysis_start_function_where = start function is not allowed to have a `where` clause
- .label = start function cannot have a `where` clause
-
-hir_analysis_start_function_parameters = start function is not allowed to have type parameters
- .label = start function cannot have type parameters
-
-hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
-
-hir_analysis_main_function_async = `main` function is not allowed to be `async`
- .label = `main` function is not allowed to be `async`
-
-hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
- .label = `main` cannot have generic parameters
-
-hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
- .label = C-variadic function must have a compatible calling convention
-
-hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
- cannot capture late-bound type parameter in a constant
- .label = parameter defined here
-
-hir_analysis_cannot_capture_late_bound_const_in_anon_const =
- cannot capture late-bound const parameter in a constant
- .label = parameter defined here
-
-hir_analysis_variances_of = {$variances_of}
+hir_analysis_parenthesized_fn_trait_expansion =
+ parenthesized trait syntax expands to `{$expanded_type}`
hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
.suggestion = cast the value to `{$cast_ty}`
.help = cast the value to `{$cast_ty}`
-hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+ .label = not allowed in type signatures
-hir_analysis_invalid_union_field =
- field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
- .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
-
-hir_analysis_invalid_union_field_sugg =
- wrap the field type in `ManuallyDrop<...>`
-
-hir_analysis_return_type_notation_on_non_rpitit =
- return type notation used on function that is not `async` and does not return `impl Trait`
- .note = function returns `{$ty}`, which is not compatible with associated type return bounds
- .label = this function must be `async` or return `impl Trait`
+hir_analysis_return_type_notation_conflicting_bound =
+ ambiguous associated function `{$assoc_name}` for `{$ty_name}`
+ .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
hir_analysis_return_type_notation_equality_bound =
return type notation is not allowed to use type equality
@@ -194,100 +198,96 @@
hir_analysis_return_type_notation_missing_method =
cannot find associated function `{$assoc_name}` for `{$ty_name}`
-hir_analysis_return_type_notation_conflicting_bound =
- ambiguous associated function `{$assoc_name}` for `{$ty_name}`
- .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
+hir_analysis_return_type_notation_on_non_rpitit =
+ return type notation used on function that is not `async` and does not return `impl Trait`
+ .note = function returns `{$ty}`, which is not compatible with associated type return bounds
+ .label = this function must be `async` or return `impl Trait`
-hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
- .label = not allowed in type signatures
-
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
- .suggestion = use a fully qualified path with inferred lifetimes
-
-hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
-
-hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
- .label = overflowed on value after {$discr}
- .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
-
-hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
- .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
-
-hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-
-hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
-
-hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
- .note = required by this annotation
-
-hir_analysis_must_implement_not_function = not a function
-
-hir_analysis_must_implement_not_function_span_note = required by this annotation
-
-hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
-
-hir_analysis_function_not_found_in_trait = function not found in this trait
-
-hir_analysis_functions_names_duplicated = functions names are duplicated
- .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+hir_analysis_self_in_impl_self =
+ `Self` is not valid in the self type of an impl block
+ .note = replace `Self` with a different type
hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
.help = add `#![feature(simd_ffi)]` to the crate attributes to enable
-hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
- .label = cannot specialize default item `{$ident}`
- .ok_label = parent `impl` is here
- .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
+hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
+ .help = add `#![feature(min_specialization)]` to the crate attributes to enable
-hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
- .note = parent implementation is in crate `{$cname}`
+hir_analysis_start_function_parameters = start function is not allowed to have type parameters
+ .label = start function cannot have type parameters
-hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
- .label = missing `{$missing_items_msg}` in implementation
+hir_analysis_start_function_where = start function is not allowed to have a `where` clause
+ .label = start function cannot have a `where` clause
-hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+hir_analysis_start_not_async = `start` is not allowed to be `async`
+ .label = `start` is not allowed to be `async`
-hir_analysis_missing_trait_item_label = `{$item}` from trait
+hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
+ .label = `start` is not allowed to have `#[target_feature]`
-hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
- .label = missing one of `{$missing_items_msg}` in implementation
- .note = required because of this annotation
+hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
+ .label = `start` is not allowed to be `#[track_caller]`
-hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
- .note = default implementation of `{$missing_item_name}` is unstable
- .some_note = use of unstable library feature '{$feature}': {$r}
- .none_note = use of unstable library feature '{$feature}'
+hir_analysis_static_specialize = cannot specialize on `'static` lifetime
+
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+
+hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
+
+hir_analysis_too_large_static = extern static is too large for the current architecture
+
+hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
+ .suggestion = remove this annotation
+
+hir_analysis_trait_object_declared_with_no_traits =
+ at least one trait is required for an object type
+ .alias_span = this alias does not contain a trait
hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
.label = needs exactly one variant, but has {$number}
.many_label = too many variants in `{$path}`
.multi_label = variant here
-hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
- .label = needs at most one non-zero-sized field, but has {$field_count}
- .labels = this field is non-zero-sized
-
hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
.label = needs at most one non-zero-sized field, but has {$field_count}
.labels = this field is non-zero-sized
-hir_analysis_too_large_static = extern static is too large for the current architecture
+hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+ .label = needs at most one non-zero-sized field, but has {$field_count}
+ .labels = this field is non-zero-sized
-hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
- .help = add `#![feature(min_specialization)]` to the crate attributes to enable
+hir_analysis_typeof_reserved_keyword_used =
+ `typeof` is a reserved keyword but unimplemented
+ .suggestion = consider replacing `typeof(...)` with an actual type
+ .label = reserved keyword
-hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
- .label = `for<...>` is here
+hir_analysis_unconstrained_opaque_type = unconstrained opaque type
+ .note = `{$name}` must be used in combination with a concrete type within the same {$what}
-hir_analysis_empty_specialization = specialization impl does not specialize any associated items
- .note = impl is a specialization of this impl
+hir_analysis_unrecognized_atomic_operation =
+ unrecognized atomic operation function: `{$op}`
+ .label = unrecognized atomic operation
-hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+hir_analysis_unrecognized_intrinsic_function =
+ unrecognized intrinsic function: `{$name}`
+ .label = unrecognized intrinsic
-hir_analysis_static_specialize = cannot specialize on `'static` lifetime
+hir_analysis_value_of_associated_struct_already_specified =
+ the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
+ .label = re-bound here
+ .previous_bound_label = `{$item_name}` bound here first
-hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
+ .label = C-variadic function must have a compatible calling convention
-hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+hir_analysis_variances_of = {$variances_of}
-hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
+ .label = `main` cannot have a `where` clause
+
+hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
+ intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
+ .label = expected {$expected} {$descr} {$expected ->
+ [one] parameter
+ *[other] parameters
+ }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index cf082f1..2c60a06 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1159,7 +1159,7 @@
// those that do.
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, trait_ref),
- trait_ref.print_only_trait_path(),
+ trait_ref.skip_binder().print_only_trait_name(),
binding.item_name,
path_span,
match binding.kind {
@@ -2625,7 +2625,7 @@
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
- trait_ref.map_or(false, |trait_ref| {
+ trait_ref.is_some_and(|trait_ref| {
let impl_ = trait_ref.subst(
tcx,
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
@@ -3654,7 +3654,7 @@
..
}) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
{
- if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) {
+ if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
return;
}
let of_trait_span = of_trait_ref.path.span;
@@ -3693,7 +3693,7 @@
.source_map()
.span_to_prev_source(self_ty.span)
.ok()
- .map_or(false, |s| s.trim_end().ends_with('<'));
+ .is_some_and(|s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.trait_ref.path.is_global();
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index d3495d3..3b2c052 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -13,11 +13,12 @@
use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -800,16 +801,15 @@
let is_implemented = leaf_def
.as_ref()
- .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
+ .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
missing_items.push(tcx.associated_item(trait_item_id));
}
// true if this item is specifically implemented in this impl
- let is_implemented_here = leaf_def
- .as_ref()
- .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
+ let is_implemented_here =
+ leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
if !is_implemented_here {
let full_impl_span =
@@ -1082,8 +1082,8 @@
let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
- let zst = layout.map_or(false, |layout| layout.is_zst());
- let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
+ let zst = layout.is_ok_and(|layout| layout.is_zst());
+ let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
if !zst {
return (span, zst, align1, None);
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 8918553..b403ee9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -179,7 +179,7 @@
hir::ItemKind::Impl(impl_) => {
let is_auto = tcx
.impl_trait_ref(def_id)
- .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
+ .is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
let mut err =
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 22502bd..ca0d550 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -819,7 +819,7 @@
recovered,
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|| variant_did
- .map_or(false, |variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
+ .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
)
}
@@ -1025,7 +1025,7 @@
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
}
Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
- ty_opt.map_or(false, is_suggestable_infer_ty)
+ ty_opt.is_some_and(is_suggestable_infer_ty)
|| segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
}
_ => false,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 97c6cb4..8e082d3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,10 +1,7 @@
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{HirId, Node};
-use rustc_middle::hir::nested_filter;
+use rustc_hir::HirId;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
@@ -14,7 +11,8 @@
use super::ItemCtxt;
use super::{bad_placeholder, is_suggestable_infer_ty};
-use crate::errors::UnconstrainedOpaqueType;
+
+mod opaque;
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
@@ -429,7 +427,7 @@
ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
- }) => find_opaque_ty_constraints_for_tait(tcx, def_id),
+ }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
// Opaque types desugared from `impl Trait`.
ItemKind::OpaqueTy(OpaqueTy {
origin:
@@ -443,7 +441,7 @@
"tried to get type of this RPITIT with no definition"
);
}
- find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+ opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
}
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
@@ -502,304 +500,6 @@
ty::EarlyBinder(output)
}
-#[instrument(skip(tcx), level = "debug")]
-/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
-/// laid for "higher-order pattern unification".
-/// This ensures that inference is tractable.
-/// In particular, definitions of opaque types can only use other generics as arguments,
-/// and they cannot repeat an argument. Example:
-///
-/// ```ignore (illustrative)
-/// type Foo<A, B> = impl Bar<A, B>;
-///
-/// // Okay -- `Foo` is applied to two distinct, generic types.
-/// fn a<T, U>() -> Foo<T, U> { .. }
-///
-/// // Not okay -- `Foo` is applied to `T` twice.
-/// fn b<T>() -> Foo<T, T> { .. }
-///
-/// // Not okay -- `Foo` is applied to a non-generic type.
-/// fn b<T>() -> Foo<T, u32> { .. }
-/// ```
-///
-fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
- use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
- struct ConstraintLocator<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- /// def_id of the opaque type whose defining uses are being checked
- def_id: LocalDefId,
-
- /// as we walk the defining uses, we are checking that all of them
- /// define the same hidden type. This variable is set to `Some`
- /// with the first type that we find, and then later types are
- /// checked against it (we also carry the span of that first
- /// type).
- found: Option<ty::OpaqueHiddenType<'tcx>>,
-
- /// In the presence of dead code, typeck may figure out a hidden type
- /// while borrowck will not. We collect these cases here and check at
- /// the end that we actually found a type that matches (modulo regions).
- typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
- }
-
- impl ConstraintLocator<'_> {
- #[instrument(skip(self), level = "debug")]
- fn check(&mut self, item_def_id: LocalDefId) {
- // Don't try to check items that cannot possibly constrain the type.
- if !self.tcx.has_typeck_results(item_def_id) {
- debug!("no constraint: no typeck results");
- return;
- }
- // Calling `mir_borrowck` can lead to cycle errors through
- // const-checking, avoid calling it if we don't have to.
- // ```rust
- // type Foo = impl Fn() -> usize; // when computing type for this
- // const fn bar() -> Foo {
- // || 0usize
- // }
- // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
- // // because we again need to reveal `Foo` so we can check whether the
- // // constant does not contain interior mutability.
- // ```
- let tables = self.tcx.typeck(item_def_id);
- if let Some(guar) = tables.tainted_by_errors {
- self.found =
- Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
- return;
- }
- let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
- debug!("no constraints in typeck results");
- return;
- };
- if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
- self.typeck_types.push(typeck_hidden_ty);
- }
-
- // Use borrowck to get the type with unerased regions.
- let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
- debug!(?concrete_opaque_types);
- if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
- debug!(?concrete_type, "found constraint");
- if let Some(prev) = &mut self.found {
- if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
- let guar =
- prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
- prev.ty = self.tcx.ty_error(guar);
- }
- } else {
- self.found = Some(concrete_type);
- }
- }
- }
- }
-
- impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
- fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
- if let hir::ExprKind::Closure(closure) = ex.kind {
- self.check(closure.def_id);
- }
- intravisit::walk_expr(self, ex);
- }
- fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_item(self, it);
- }
- }
- fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_impl_item(self, it);
- }
- }
- fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.owner_id);
- self.check(it.owner_id.def_id);
- intravisit::walk_trait_item(self, it);
- }
- }
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let scope = tcx.hir().get_defining_scope(hir_id);
- let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
-
- debug!(?scope);
-
- if scope == hir::CRATE_HIR_ID {
- tcx.hir().walk_toplevel_module(&mut locator);
- } else {
- trace!("scope={:#?}", tcx.hir().get(scope));
- match tcx.hir().get(scope) {
- // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
- // This allows our visitor to process the defining item itself, causing
- // it to pick up any 'sibling' defining uses.
- //
- // For example, this code:
- // ```
- // fn foo() {
- // type Blah = impl Debug;
- // let my_closure = || -> Blah { true };
- // }
- // ```
- //
- // requires us to explicitly process `foo()` in order
- // to notice the defining usage of `Blah`.
- Node::Item(it) => locator.visit_item(it),
- Node::ImplItem(it) => locator.visit_impl_item(it),
- Node::TraitItem(it) => locator.visit_trait_item(it),
- other => bug!("{:?} is not a valid scope for an opaque type item", other),
- }
- }
-
- let Some(hidden) = locator.found else {
- let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
- span: tcx.def_span(def_id),
- name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
- what: match tcx.hir().get(scope) {
- _ if scope == hir::CRATE_HIR_ID => "module",
- Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
- Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
- _ => "item",
- },
- });
- return tcx.ty_error(reported);
- };
-
- // Only check against typeck if we didn't already error
- if !hidden.ty.references_error() {
- for concrete_type in locator.typeck_types {
- if concrete_type.ty != tcx.erase_regions(hidden.ty)
- && !(concrete_type, hidden).references_error()
- {
- hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
- }
- }
- }
-
- hidden.ty
-}
-
-fn find_opaque_ty_constraints_for_rpit(
- tcx: TyCtxt<'_>,
- def_id: LocalDefId,
- owner_def_id: LocalDefId,
-) -> Ty<'_> {
- use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
- struct ConstraintChecker<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- /// def_id of the opaque type whose defining uses are being checked
- def_id: LocalDefId,
-
- found: ty::OpaqueHiddenType<'tcx>,
- }
-
- impl ConstraintChecker<'_> {
- #[instrument(skip(self), level = "debug")]
- fn check(&self, def_id: LocalDefId) {
- // Use borrowck to get the type with unerased regions.
- let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
- debug!(?concrete_opaque_types);
- for (&def_id, &concrete_type) in concrete_opaque_types {
- if def_id != self.def_id {
- // Ignore constraints for other opaque types.
- continue;
- }
-
- debug!(?concrete_type, "found constraint");
-
- if concrete_type.ty != self.found.ty
- && !(concrete_type, self.found).references_error()
- {
- self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
- }
- }
- }
- }
-
- impl<'tcx> intravisit::Visitor<'tcx> for ConstraintChecker<'tcx> {
- type NestedFilter = nested_filter::OnlyBodies;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
- fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
- if let hir::ExprKind::Closure(closure) = ex.kind {
- self.check(closure.def_id);
- }
- intravisit::walk_expr(self, ex);
- }
- fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_item(self, it);
- }
- }
- fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_impl_item(self, it);
- }
- }
- fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.owner_id);
- self.check(it.owner_id.def_id);
- intravisit::walk_trait_item(self, it);
- }
- }
-
- let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
-
- if let Some(concrete) = concrete {
- let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
- debug!(?scope);
- let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
-
- match tcx.hir().get(scope) {
- Node::Item(it) => intravisit::walk_item(&mut locator, it),
- Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
- Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
- other => bug!("{:?} is not a valid scope for an opaque type item", other),
- }
- }
-
- concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
- let table = tcx.typeck(owner_def_id);
- if let Some(guar) = table.tainted_by_errors {
- // Some error in the
- // owner fn prevented us from populating
- // the `concrete_opaque_types` table.
- tcx.ty_error(guar)
- } else {
- table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
- // We failed to resolve the opaque type or it
- // resolves to itself. We interpret this as the
- // no values of the hidden type ever being constructed,
- // so we can just make the hidden type be `!`.
- // For backwards compatibility reasons, we fall back to
- // `()` until we the diverging default is changed.
- tcx.mk_diverging_default()
- })
- }
- })
-}
-
fn infer_placeholder_type<'a>(
tcx: TyCtxt<'a>,
def_id: LocalDefId,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
new file mode 100644
index 0000000..f7c5b44
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -0,0 +1,298 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
+
+use crate::errors::UnconstrainedOpaqueType;
+
+/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
+/// laid for "higher-order pattern unification".
+/// This ensures that inference is tractable.
+/// In particular, definitions of opaque types can only use other generics as arguments,
+/// and they cannot repeat an argument. Example:
+///
+/// ```ignore (illustrative)
+/// type Foo<A, B> = impl Bar<A, B>;
+///
+/// // Okay -- `Foo` is applied to two distinct, generic types.
+/// fn a<T, U>() -> Foo<T, U> { .. }
+///
+/// // Not okay -- `Foo` is applied to `T` twice.
+/// fn b<T>() -> Foo<T, T> { .. }
+///
+/// // Not okay -- `Foo` is applied to a non-generic type.
+/// fn b<T>() -> Foo<T, u32> { .. }
+/// ```
+#[instrument(skip(tcx), level = "debug")]
+pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let scope = tcx.hir().get_defining_scope(hir_id);
+ let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+
+ debug!(?scope);
+
+ if scope == hir::CRATE_HIR_ID {
+ tcx.hir().walk_toplevel_module(&mut locator);
+ } else {
+ trace!("scope={:#?}", tcx.hir().get(scope));
+ match tcx.hir().get(scope) {
+ // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
+ // This allows our visitor to process the defining item itself, causing
+ // it to pick up any 'sibling' defining uses.
+ //
+ // For example, this code:
+ // ```
+ // fn foo() {
+ // type Blah = impl Debug;
+ // let my_closure = || -> Blah { true };
+ // }
+ // ```
+ //
+ // requires us to explicitly process `foo()` in order
+ // to notice the defining usage of `Blah`.
+ Node::Item(it) => locator.visit_item(it),
+ Node::ImplItem(it) => locator.visit_impl_item(it),
+ Node::TraitItem(it) => locator.visit_trait_item(it),
+ other => bug!("{:?} is not a valid scope for an opaque type item", other),
+ }
+ }
+
+ let Some(hidden) = locator.found else {
+ let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
+ span: tcx.def_span(def_id),
+ name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
+ what: match tcx.hir().get(scope) {
+ _ if scope == hir::CRATE_HIR_ID => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
+ _ => "item",
+ },
+ });
+ return tcx.ty_error(reported);
+ };
+
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if concrete_type.ty != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+ }
+ }
+ }
+
+ hidden.ty
+}
+
+struct TaitConstraintLocator<'tcx> {
+ tcx: TyCtxt<'tcx>,
+
+ /// def_id of the opaque type whose defining uses are being checked
+ def_id: LocalDefId,
+
+ /// as we walk the defining uses, we are checking that all of them
+ /// define the same hidden type. This variable is set to `Some`
+ /// with the first type that we find, and then later types are
+ /// checked against it (we also carry the span of that first
+ /// type).
+ found: Option<ty::OpaqueHiddenType<'tcx>>,
+
+ /// In the presence of dead code, typeck may figure out a hidden type
+ /// while borrowck will not. We collect these cases here and check at
+ /// the end that we actually found a type that matches (modulo regions).
+ typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
+}
+
+impl TaitConstraintLocator<'_> {
+ #[instrument(skip(self), level = "debug")]
+ fn check(&mut self, item_def_id: LocalDefId) {
+ // Don't try to check items that cannot possibly constrain the type.
+ if !self.tcx.has_typeck_results(item_def_id) {
+ debug!("no constraint: no typeck results");
+ return;
+ }
+ // Calling `mir_borrowck` can lead to cycle errors through
+ // const-checking, avoid calling it if we don't have to.
+ // ```rust
+ // type Foo = impl Fn() -> usize; // when computing type for this
+ // const fn bar() -> Foo {
+ // || 0usize
+ // }
+ // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
+ // // because we again need to reveal `Foo` so we can check whether the
+ // // constant does not contain interior mutability.
+ // ```
+ let tables = self.tcx.typeck(item_def_id);
+ if let Some(guar) = tables.tainted_by_errors {
+ self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+ return;
+ }
+ let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+ debug!("no constraints in typeck results");
+ return;
+ };
+ if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
+ self.typeck_types.push(typeck_hidden_ty);
+ }
+
+ // Use borrowck to get the type with unerased regions.
+ let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
+ debug!(?concrete_opaque_types);
+ if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
+ debug!(?concrete_type, "found constraint");
+ if let Some(prev) = &mut self.found {
+ if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+ let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+ prev.ty = self.tcx.ty_error(guar);
+ }
+ } else {
+ self.found = Some(concrete_type);
+ }
+ }
+ }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.tcx.hir()
+ }
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+ if let hir::ExprKind::Closure(closure) = ex.kind {
+ self.check(closure.def_id);
+ }
+ intravisit::walk_expr(self, ex);
+ }
+ fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_item(self, it);
+ }
+ }
+ fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_impl_item(self, it);
+ }
+ }
+ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
+ intravisit::walk_trait_item(self, it);
+ }
+}
+
+pub(super) fn find_opaque_ty_constraints_for_rpit(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+ owner_def_id: LocalDefId,
+) -> Ty<'_> {
+ let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+
+ if let Some(concrete) = concrete {
+ let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
+ debug!(?scope);
+ let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+
+ match tcx.hir().get(scope) {
+ Node::Item(it) => intravisit::walk_item(&mut locator, it),
+ Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
+ Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
+ other => bug!("{:?} is not a valid scope for an opaque type item", other),
+ }
+ }
+
+ concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
+ let table = tcx.typeck(owner_def_id);
+ if let Some(guar) = table.tainted_by_errors {
+ // Some error in the
+ // owner fn prevented us from populating
+ // the `concrete_opaque_types` table.
+ tcx.ty_error(guar)
+ } else {
+ table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // We failed to resolve the opaque type or it
+ // resolves to itself. We interpret this as the
+ // no values of the hidden type ever being constructed,
+ // so we can just make the hidden type be `!`.
+ // For backwards compatibility reasons, we fall back to
+ // `()` until we the diverging default is changed.
+ tcx.mk_diverging_default()
+ })
+ }
+ })
+}
+
+struct RpitConstraintChecker<'tcx> {
+ tcx: TyCtxt<'tcx>,
+
+ /// def_id of the opaque type whose defining uses are being checked
+ def_id: LocalDefId,
+
+ found: ty::OpaqueHiddenType<'tcx>,
+}
+
+impl RpitConstraintChecker<'_> {
+ #[instrument(skip(self), level = "debug")]
+ fn check(&self, def_id: LocalDefId) {
+ // Use borrowck to get the type with unerased regions.
+ let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+ debug!(?concrete_opaque_types);
+ for (&def_id, &concrete_type) in concrete_opaque_types {
+ if def_id != self.def_id {
+ // Ignore constraints for other opaque types.
+ continue;
+ }
+
+ debug!(?concrete_type, "found constraint");
+
+ if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
+ {
+ self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+ }
+ }
+ }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
+ type NestedFilter = nested_filter::OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.tcx.hir()
+ }
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+ if let hir::ExprKind::Closure(closure) = ex.kind {
+ self.check(closure.def_id);
+ }
+ intravisit::walk_expr(self, ex);
+ }
+ fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_item(self, it);
+ }
+ }
+ fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_impl_item(self, it);
+ }
+ }
+ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
+ intravisit::walk_trait_item(self, it);
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 6d1a163..ee34572 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -395,7 +395,7 @@
) -> String {
let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
let is_used_in_input = |def_id| {
- fn_sig.map_or(false, |fn_sig| {
+ fn_sig.is_some_and(|fn_sig| {
fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(
None,
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 4a669e3..aab432e 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -1,67 +1,20 @@
-hir_typeck_field_multiply_specified_in_initializer =
- field `{$ident}` specified more than once
- .label = used more than once
- .previous_use_label = first use of `{$ident}`
-
-hir_typeck_functional_record_update_on_non_struct =
- functional record update syntax requires a struct
-
-hir_typeck_return_stmt_outside_of_fn_body =
- return statement outside of function body
- .encl_body_label = the return is part of this body...
- .encl_fn_label = ...not the enclosing function body
-
-hir_typeck_yield_expr_outside_of_generator =
- yield expression outside of generator literal
-
-hir_typeck_struct_expr_non_exhaustive =
- cannot create non-exhaustive {$what} using struct expression
-
-hir_typeck_method_call_on_unknown_type =
- the type of this value must be known to call a method on a raw pointer on it
-
-hir_typeck_address_of_temporary_taken = cannot take address of a temporary
- .label = temporary value
+hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
hir_typeck_add_return_type_add = try adding a return type
hir_typeck_add_return_type_missing_here = a return type might be missing here
-hir_typeck_expected_default_return_type = expected `()` because of default return type
+hir_typeck_address_of_temporary_taken = cannot take address of a temporary
+ .label = temporary value
-hir_typeck_expected_return_type = expected `{$expected}` because of return type
+hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
+ .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
-hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
-
-hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
-
-hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
-hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
-
-hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
-
-hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
- .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
-hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
- .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
-hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-
-hir_typeck_convert_to_str = try converting the passed type into a `&str`
-
-hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
-
-hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
-hir_typeck_fru_expr = this expression does not end in a comma...
-hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
-hir_typeck_fru_suggestion =
- to set the remaining fields{$expr ->
- [NONE]{""}
- *[other] {" "}from `{$expr}`
- }, separate the last named field with a comma
+hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
+ [NONE] {""}
+ [implement] , perhaps you need to implement it
+ *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
+}
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
.help = consult the documentation on `const_eval_select` for more information
@@ -70,23 +23,72 @@
.note = expected a function item, found {$ty}
.help = consult the documentation on `const_eval_select` for more information
-hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
-hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
-hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
- .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
+hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
-hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+hir_typeck_expected_default_return_type = expected `()` because of default return type
-hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
+hir_typeck_expected_return_type = expected `{$expected}` because of return type
+
+hir_typeck_field_multiply_specified_in_initializer =
+ field `{$ident}` specified more than once
+ .label = used more than once
+ .previous_use_label = first use of `{$ident}`
+
+hir_typeck_fru_expr = this expression does not end in a comma...
+hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
+hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
+hir_typeck_fru_suggestion =
+ to set the remaining fields{$expr ->
+ [NONE]{""}
+ *[other] {" "}from `{$expr}`
+ }, separate the last named field with a comma
+
+hir_typeck_functional_record_update_on_non_struct =
+ functional record update syntax requires a struct
+
+hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
+hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
+
+hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
+ .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
+ .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_method_call_on_unknown_raw_pointee =
+ cannot call a method on a raw pointer with an unknown pointee type
+
+hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
[true] {""}
*[other] {" "}in the current scope
}
-hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
- [NONE] {""}
- [implement] , perhaps you need to implement it
- *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
-}
+hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
+
+hir_typeck_return_stmt_outside_of_fn_body =
+ return statement outside of function body
+ .encl_body_label = the return is part of this body...
+ .encl_fn_label = ...not the enclosing function body
+
+hir_typeck_struct_expr_non_exhaustive =
+ cannot create non-exhaustive {$what} using struct expression
+
+hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+
+hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
+
+hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
+
+hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
+hir_typeck_yield_expr_outside_of_generator =
+ yield expression outside of generator literal
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index a92f368..98c683f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -465,7 +465,7 @@
.sess
.source_map()
.span_to_snippet(self.expr_span)
- .map_or(false, |snip| snip.starts_with('('));
+ .is_ok_and(|snip| snip.starts_with('('));
// Very crude check to see whether the expression must be wrapped
// in parentheses for the suggestion to work (issue #89497).
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index cfe8d59..08c4082 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1814,7 +1814,7 @@
.span_to_snippet(return_sp)
.unwrap_or_else(|_| "dyn Trait".to_string());
let mut snippet_iter = snippet.split_whitespace();
- let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
+ let has_impl = snippet_iter.next().is_some_and(|s| s == "impl");
// Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
let mut is_object_safe = false;
if let hir::FnRetTy::Return(ty) = fn_output
@@ -1834,7 +1834,7 @@
bound
.trait_ref()
.and_then(|t| t.trait_def_id())
- .map_or(false, |def_id| {
+ .is_some_and(|def_id| {
fcx.tcx.check_is_object_safe(def_id)
})
})
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 2defca5..b50630e 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1748,8 +1748,7 @@
|err: &mut Diagnostic,
found_to_exp_is_fallible: bool,
exp_to_found_is_fallible: bool| {
- let exp_is_lhs =
- expected_ty_expr.map(|e| self.tcx.hir().is_lhs(e.hir_id)).unwrap_or(false);
+ let exp_is_lhs = expected_ty_expr.is_some_and(|e| self.tcx.hir().is_lhs(e.hir_id));
if exp_is_lhs {
return;
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 102a313..4222205 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -49,8 +49,8 @@
}
#[derive(Diagnostic)]
-#[diag(hir_typeck_method_call_on_unknown_type, code = "E0699")]
-pub struct MethodCallOnUnknownType {
+#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = "E0699")]
+pub struct MethodCallOnUnknownRawPointee {
#[primary_span]
pub span: Span,
}
@@ -319,3 +319,11 @@
pub item_name: Ident,
pub action_or_ty: String,
}
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_ctor_is_private, code = "E0603")]
+pub struct CtorIsPrivate {
+ #[primary_span]
+ pub span: Span,
+ pub def: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index adc1b09..19ff77d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -497,7 +497,7 @@
.borrow()
.adjustments()
.get(base.hir_id)
- .map_or(false, |x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
+ .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
});
if !is_named {
self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span });
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 94b6a0f..e14e8ac 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -438,12 +438,19 @@
// to borrow discr.
needs_to_be_read = true;
}
- PatKind::Or(_)
- | PatKind::Box(_)
- | PatKind::Slice(..)
- | PatKind::Ref(..)
- | PatKind::Wild => {
- // If the PatKind is Or, Box, Slice or Ref, the decision is made later
+ PatKind::Slice(lhs, wild, rhs) => {
+ // We don't need to test the length if the pattern is `[..]`
+ if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
+ // Arrays have a statically known size, so
+ // there is no need to read their length
+ || discr_place.place.base_ty.is_array()
+ {
+ } else {
+ needs_to_be_read = true;
+ }
+ }
+ PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => {
+ // If the PatKind is Or, Box, or Ref, the decision is made later
// as these patterns contains subpatterns
// If the PatKind is Wild, the decision is made based on the other patterns being
// examined
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 9721e3b..5579503 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1,4 +1,5 @@
use crate::callee::{self, DeferredCallResolution};
+use crate::errors::CtorIsPrivate;
use crate::method::{self, MethodCallee, SelfSource};
use crate::rvalue_scopes;
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
@@ -1017,8 +1018,8 @@
.typeck_results
.borrow()
.expr_ty_adjusted_opt(rcvr)
- .and_then(|ty| expected.map(|expected_ty| expected_ty.peel_refs() == ty.peel_refs()))
- .unwrap_or(false);
+ .zip(expected)
+ .is_some_and(|(ty, expected_ty)| expected_ty.peel_refs() == ty.peel_refs());
let prev_call_mutates_and_returns_unit = || {
self.typeck_results
@@ -1026,14 +1027,13 @@
.type_dependent_def_id(expr.hir_id)
.map(|def_id| self.tcx.fn_sig(def_id).skip_binder().skip_binder())
.and_then(|sig| sig.inputs_and_output.split_last())
- .map(|(output, inputs)| {
+ .is_some_and(|(output, inputs)| {
output.is_unit()
&& inputs
.get(0)
.and_then(|self_ty| self_ty.ref_mutability())
- .map_or(false, rustc_ast::Mutability::is_mut)
+ .is_some_and(rustc_ast::Mutability::is_mut)
})
- .unwrap_or(false)
};
if !(rcvr_has_the_expected_type || prev_call_mutates_and_returns_unit()) {
@@ -1200,16 +1200,20 @@
}
}
- let has_self = path_segs
- .last()
- .map(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self)
- .unwrap_or(false);
+ let has_self =
+ path_segs.last().is_some_and(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self);
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).subst_identity());
match ty.normalized.ty_adt_def() {
Some(adt_def) if adt_def.has_ctor() => {
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
+ // Check the visibility of the ctor.
+ let vis = tcx.visibility(ctor_def_id);
+ if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) {
+ tcx.sess
+ .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
+ }
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let user_substs = Self::user_substs_for_adt(ty);
user_self_ty = user_substs.user_self_ty;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index c7011b2..72c42f8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -876,7 +876,7 @@
let mut errors = errors.into_iter().peekable();
let mut only_extras_so_far = errors
.peek()
- .map_or(false, |first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
+ .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
let mut suggestions = vec![];
while let Some(error) = errors.next() {
only_extras_so_far &= matches!(error, Error::Extra(_));
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index cd3966a..ecafbd6 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -193,7 +193,7 @@
.get(&TrackedValue::Temporary(hir_id))
.or(self.tracked_value_map.get(&TrackedValue::Variable(hir_id)))
.cloned()
- .map_or(false, |tracked_value_id| {
+ .is_some_and(|tracked_value_id| {
self.expect_node(location.into()).drop_state.contains(tracked_value_id)
})
}
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 4110b17..294c3bb 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -4,7 +4,8 @@
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
-use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap;
@@ -130,7 +131,7 @@
// (*) binder skipped
if let ty::PredicateKind::Clause(ty::Clause::Trait(tpred)) = obligation.predicate.kind().skip_binder()
&& let Some(ty) = self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
- && self.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
+ && self.tcx.lang_items().sized_trait().is_some_and(|st| st != tpred.trait_ref.def_id)
{
let new_self_ty = self.tcx.types.unit;
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index f5fca14..78171e0 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -411,7 +411,7 @@
}
Res::Local(var_id) => {
- if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) {
+ if self.upvars.is_some_and(|upvars| upvars.contains_key(&var_id)) {
self.cat_upvar(hir_id, var_id)
} else {
Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new()))
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index f91f4f8..9f3d35a 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -3,7 +3,7 @@
use super::MethodError;
use super::NoMatchData;
-use crate::errors::MethodCallOnUnknownType;
+use crate::errors::MethodCallOnUnknownRawPointee;
use crate::FnCtxt;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@@ -438,7 +438,7 @@
// so we do a future-compat lint here for the 2015 edition
// (see https://github.com/rust-lang/rust/issues/46906)
if self.tcx.sess.rust_2018() {
- self.tcx.sess.emit_err(MethodCallOnUnknownType { span });
+ self.tcx.sess.emit_err(MethodCallOnUnknownRawPointee { span });
} else {
self.tcx.struct_span_lint_hir(
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
@@ -1194,7 +1194,7 @@
pick.autoderefs += 1;
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
mutbl,
- unsize: pick.autoref_or_ptr_adjustment.map_or(false, |a| a.get_unsize()),
+ unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
})
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 1736450..8555c20 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -356,7 +356,7 @@
}
}
- let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.map_or(false, |def_id| {
+ let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_name.name == Symbol::intern("write_fmt");
@@ -1522,7 +1522,7 @@
let span_included = match parent_expr.kind {
hir::ExprKind::Struct(_, eps, _) => {
- eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
+ eps.len() > 0 && eps.last().is_some_and(|ep| ep.span.contains(span))
}
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
@@ -1781,7 +1781,7 @@
ProbeScope::TraitsInScope,
return_type,
)
- .map_or(false, |pick| {
+ .is_ok_and(|pick| {
!never_mention_traits
.iter()
.flatten()
@@ -2468,7 +2468,7 @@
// implement the `AsRef` trait.
let skip = skippable.contains(&did)
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
- || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
+ || inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
@@ -2755,7 +2755,7 @@
let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
let imp_simp =
simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
- imp_simp.map_or(false, |s| s == simp_rcvr_ty)
+ imp_simp.is_some_and(|s| s == simp_rcvr_ty)
})
{
explicitly_negative.push(candidate);
@@ -2893,7 +2893,7 @@
match ty.kind() {
ty::Adt(def, _) => def.did().is_local(),
ty::Foreign(did) => did.is_local(),
- ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
+ ty::Dynamic(tr, ..) => tr.principal().is_some_and(|d| d.def_id().is_local()),
ty::Param(_) => true,
// Everything else (primitive types, etc.) is effectively
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index af351a3..b8bf2b6 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -549,9 +549,8 @@
let to_owned_msg = "create an owned `String` from a string reference";
let string_type = self.tcx.lang_items().string();
- let is_std_string = |ty: Ty<'tcx>| {
- ty.ty_adt_def().map_or(false, |ty_def| Some(ty_def.did()) == string_type)
- };
+ let is_std_string =
+ |ty: Ty<'tcx>| ty.ty_adt_def().is_some_and(|ty_def| Some(ty_def.did()) == string_type);
match (lhs_ty.kind(), rhs_ty.kind()) {
(&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
@@ -760,8 +759,7 @@
span,
traits::BinOp {
rhs_span: opt_rhs_expr.map(|expr| expr.span),
- is_lit: opt_rhs_expr
- .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
+ is_lit: opt_rhs_expr.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: expected.only_has_type(self),
},
);
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index f217c5c..e2b1dc0 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -329,7 +329,7 @@
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
// This helps avoid accidental drops.
if inside_union
- && source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
+ && source.ty_adt_def().is_some_and(|adt| adt.is_manually_drop())
{
let mut err = self.tcx.sess.struct_span_err(
expr.span,
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 543194a..9458099 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -972,15 +972,11 @@
let mut obligations_should_hold = Vec::new();
// Checks if a root variable implements any of the auto traits
for check_trait in auto_traits_def_id.iter() {
- obligations_should_hold.push(
- check_trait
- .map(|check_trait| {
- self.infcx
- .type_implements_trait(check_trait, [ty], self.param_env)
- .must_apply_modulo_regions()
- })
- .unwrap_or(false),
- );
+ obligations_should_hold.push(check_trait.is_some_and(|check_trait| {
+ self.infcx
+ .type_implements_trait(check_trait, [ty], self.param_env)
+ .must_apply_modulo_regions()
+ }));
}
let mut problematic_captures = FxHashMap::default();
@@ -996,15 +992,11 @@
// Checks if a capture implements any of the auto traits
let mut obligations_holds_for_capture = Vec::new();
for check_trait in auto_traits_def_id.iter() {
- obligations_holds_for_capture.push(
- check_trait
- .map(|check_trait| {
- self.infcx
- .type_implements_trait(check_trait, [ty], self.param_env)
- .must_apply_modulo_regions()
- })
- .unwrap_or(false),
- );
+ obligations_holds_for_capture.push(check_trait.is_some_and(|check_trait| {
+ self.infcx
+ .type_implements_trait(check_trait, [ty], self.param_env)
+ .must_apply_modulo_regions()
+ }));
}
let mut capture_problems = FxHashSet::default();
diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl
index b760620..9fa4e0f 100644
--- a/compiler/rustc_incremental/messages.ftl
+++ b/compiler/rustc_incremental/messages.ftl
@@ -1,118 +1,118 @@
-incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+incremental_assert_loaded =
+ we asserted that an existing incremental cache directory should be successfully loaded, but it was not
-incremental_missing_depnode = missing `DepNode` variant
-
-incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
-
-incremental_no_path = no path from `{$source}` to `{$target}`
-
-incremental_ok = OK
-
-incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
-
-incremental_missing_query_depgraph =
- found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
-
-incremental_malformed_cgu_name =
- found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
-
-incremental_no_module_named =
- no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
-
-incremental_field_associated_value_expected = associated value expected for `{$name}`
-
-incremental_no_field = no field `{$name}`
+incremental_assert_not_loaded =
+ we asserted that the incremental cache should not be loaded, but it was loaded
incremental_assertion_auto =
`except` specified DepNodes that can not be affected for "{$name}": "{$e}"
-incremental_undefined_clean_dirty_assertions_item =
- clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
-
-incremental_undefined_clean_dirty_assertions =
- clean/dirty auto-assertions not yet defined for {$kind}
-
-incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
-
-incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
-
-incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
-
-incremental_not_clean = `{$dep_node_str}` should be clean but is not
-
-incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
-
-incremental_unknown_item = unknown item `{$name}`
-
-incremental_no_cfg = no cfg attribute
+incremental_associated_value_expected = expected an associated value
incremental_associated_value_expected_for = associated value expected for `{$ident}`
-incremental_associated_value_expected = expected an associated value
-
-incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
-
-incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
-
-incremental_create_new = failed to create {$name} at `{$path}`: {$err}
-
-incremental_write_new = failed to write {$name} to `{$path}`: {$err}
-
incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
+incremental_cargo_help_1 =
+ incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
+incremental_cargo_help_2 =
+ the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+
+incremental_copy_workproduct_to_cache =
+ error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+
+incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+
incremental_create_incr_comp_dir =
could not create incremental compilation {$tag} directory `{$path}`: {$err}
incremental_create_lock =
incremental compilation: could not create session directory lock file: {$lock_err}
-incremental_lock_unsupported =
- the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
-incremental_cargo_help_1 =
- incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
-incremental_cargo_help_2 =
- the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+incremental_create_new = failed to create {$name} at `{$path}`: {$err}
-incremental_delete_lock =
- error deleting lock file for incremental compilation session directory `{$path}`: {$err}
-
-incremental_hard_link_failed =
- hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
-
-incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+incremental_decode_incr_cache = could not decode incremental cache: {$err}
incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
-incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
-
-incremental_invalid_gc_failed =
- failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
-
-incremental_finalized_gc_failed =
- failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
-
-incremental_session_gc_failed =
- failed to garbage collect incremental compilation session directory `{$path}`: {$err}
-
-incremental_assert_not_loaded =
- we asserted that the incremental cache should not be loaded, but it was loaded
-
-incremental_assert_loaded =
- we asserted that an existing incremental cache directory should be successfully loaded, but it was not
-
incremental_delete_incompatible =
failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
+incremental_delete_lock =
+ error deleting lock file for incremental compilation session directory `{$path}`: {$err}
+
+incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
+
+incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+
+incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
+
+incremental_field_associated_value_expected = associated value expected for `{$name}`
+
+incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalized_gc_failed =
+ failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
+
+incremental_hard_link_failed =
+ hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
+
+incremental_invalid_gc_failed =
+ failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
+
incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
-incremental_decode_incr_cache = could not decode incremental cache: {$err}
+incremental_lock_unsupported =
+ the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
+incremental_malformed_cgu_name =
+ found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
-incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+incremental_missing_depnode = missing `DepNode` variant
+
+incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
+
+incremental_missing_query_depgraph =
+ found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
-incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+incremental_no_cfg = no cfg attribute
-incremental_copy_workproduct_to_cache =
- error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+incremental_no_field = no field `{$name}`
-incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
+incremental_no_module_named =
+ no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
+
+incremental_no_path = no path from `{$source}` to `{$target}`
+
+incremental_not_clean = `{$dep_node_str}` should be clean but is not
+
+incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
+
+incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
+
+incremental_ok = OK
+
+incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
+
+incremental_session_gc_failed =
+ failed to garbage collect incremental compilation session directory `{$path}`: {$err}
+
+incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
+
+incremental_undefined_clean_dirty_assertions =
+ clean/dirty auto-assertions not yet defined for {$kind}
+
+incremental_undefined_clean_dirty_assertions_item =
+ clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
+
+incremental_unknown_item = unknown item `{$name}`
+
+incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
+
+incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+
+incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
+
+incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+
+incremental_write_new = failed to write {$name} to `{$path}`: {$err}
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index a1ab9c8..15bc3b4 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1544,7 +1544,7 @@
#[inline]
pub fn contains(&self, elem: T) -> bool {
let (word_index, mask) = word_index_and_mask(elem);
- self.bit_set.words.get(word_index).map_or(false, |word| (word & mask) != 0)
+ self.bit_set.words.get(word_index).is_some_and(|word| (word & mask) != 0)
}
#[inline]
@@ -1818,7 +1818,7 @@
/// if the matrix represents (transitive) reachability, can
/// `row` reach `column`?
pub fn contains(&self, row: R, column: C) -> bool {
- self.row(row).map_or(false, |r| r.contains(column))
+ self.row(row).is_some_and(|r| r.contains(column))
}
/// Adds the bits from row `read` to the bits from row `write`, and
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index 7ed4860..d3cf267 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -181,6 +181,30 @@
self.map.is_empty()
}
+ /// Equivalent to `range.iter().find(|i| !self.contains(i))`.
+ pub fn first_unset_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
+ let start = inclusive_start(range.clone());
+ let Some(end) = inclusive_end(self.domain, range) else {
+ // empty range
+ return None;
+ };
+ if start > end {
+ return None;
+ }
+ let Some(last) = self.map.partition_point(|r| r.0 <= start).checked_sub(1) else {
+ // All ranges in the map start after the new range's end
+ return Some(I::new(start as usize));
+ };
+ let (_, prev_end) = self.map[last];
+ if start > prev_end {
+ Some(I::new(start as usize))
+ } else if prev_end < end {
+ Some(I::new(prev_end as usize + 1))
+ } else {
+ None
+ }
+ }
+
/// Returns the maximum (last) element present in the set from `range`.
pub fn last_set_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
let start = inclusive_start(range.clone());
@@ -224,7 +248,7 @@
fn check_invariants(&self) -> bool {
let mut current: Option<u32> = None;
for (start, end) in &self.map {
- if start > end || current.map_or(false, |x| x + 1 >= *start) {
+ if start > end || current.is_some_and(|x| x + 1 >= *start) {
return false;
}
current = Some(*end);
@@ -297,6 +321,6 @@
}
pub fn contains(&self, row: R, point: C) -> bool {
- self.row(row).map_or(false, |r| r.contains(point))
+ self.row(row).is_some_and(|r| r.contains(point))
}
}
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index fdc4ff0..f44c4a7 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -1,257 +1,8 @@
-infer_opaque_hidden_type =
- opaque type's hidden type cannot be another opaque type from the same scope
- .label = one of the two opaque types used here has to be outside its defining scope
- .opaque_type = opaque type whose hidden type is being assigned
- .hidden_type = opaque type being used as hidden type
-
-infer_type_annotations_needed = {$source_kind ->
- [closure] type annotations needed for the closure `{$source_name}`
- [normal] type annotations needed for `{$source_name}`
- *[other] type annotations needed
-}
- .label = type must be known at this point
-
-infer_label_bad = {$bad_kind ->
- *[other] cannot infer type
- [more_info] cannot infer {$prefix_kind ->
- *[type] type for {$prefix}
- [const_with_param] the value of const parameter
- [const] the value of the constant
- } `{$name}`{$has_parent ->
- [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
- *[false] {""}
- }
-}
-
-infer_source_kind_subdiag_let = {$kind ->
- [with_pattern] consider giving `{$name}` an explicit type
- [closure] consider giving this closure parameter an explicit type
- *[other] consider giving this pattern a type
-}{$x_kind ->
- [has_name] , where the {$prefix_kind ->
- *[type] type for {$prefix}
- [const_with_param] value of const parameter
- [const] value of the constant
- } `{$arg_name}` is specified
- [underscore] , where the placeholders `_` are specified
- *[empty] {""}
-}
-
-infer_source_kind_subdiag_generic_label =
- cannot infer {$is_type ->
- [true] type
- *[false] the value
- } of the {$is_type ->
- [true] type
- *[false] const
- } {$parent_exists ->
- [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
- *[false] parameter {$param_name}
- }
-
-infer_source_kind_subdiag_generic_suggestion =
- consider specifying the generic {$arg_count ->
- [one] argument
- *[other] arguments
- }
-
-infer_source_kind_fully_qualified =
- try using a fully qualified path to specify the expected types
-
-infer_source_kind_closure_return =
- try giving this closure an explicit return type
-
-# generator_kind may need to be translated
-infer_need_type_info_in_generator =
- type inside {$generator_kind ->
- [async_block] `async` block
- [async_closure] `async` closure
- [async_fn] `async fn` body
- *[generator] generator
- } must be known in this context
-
-
-infer_subtype = ...so that the {$requirement ->
- [method_compat] method type is compatible with trait
- [type_compat] associated type is compatible with trait
- [const_compat] const is compatible with trait
- [expr_assignable] expression is assignable
- [if_else_different] `if` and `else` have incompatible types
- [no_else] `if` missing an `else` returns `()`
- [fn_main_correct_type] `main` function has the correct type
- [fn_start_correct_type] `#[start]` function has the correct type
- [intrinsic_correct_type] intrinsic has the correct type
- [method_correct_type] method receiver has the correct type
- *[other] types are compatible
-}
-infer_subtype_2 = ...so that {$requirement ->
- [method_compat] method type is compatible with trait
- [type_compat] associated type is compatible with trait
- [const_compat] const is compatible with trait
- [expr_assignable] expression is assignable
- [if_else_different] `if` and `else` have incompatible types
- [no_else] `if` missing an `else` returns `()`
- [fn_main_correct_type] `main` function has the correct type
- [fn_start_correct_type] `#[start]` function has the correct type
- [intrinsic_correct_type] intrinsic has the correct type
- [method_correct_type] method receiver has the correct type
- *[other] types are compatible
-}
-
-infer_reborrow = ...so that reference does not outlive borrowed content
-infer_reborrow_upvar = ...so that closure can access `{$name}`
-infer_relate_object_bound = ...so that it can be closed over into an object
-infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
-infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
- [true] ...
- *[false] {""}
-}
-infer_relate_param_bound_2 = ...that is required by this bound
-infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
-infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
-infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
-
-infer_nothing = {""}
-
-infer_lifetime_mismatch = lifetime mismatch
-
-infer_declared_different = this parameter and the return type are declared with different lifetimes...
-infer_data_returned = ...but data{$label_var1_exists ->
- [true] {" "}from `{$label_var1}`
- *[false] {""}
-} is returned here
-
-infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
-infer_declared_multiple = this type is declared with multiple lifetimes...
-infer_types_declared_different = these two types are declared with different lifetimes...
-infer_data_flows = ...but data{$label_var1_exists ->
- [true] {" "}from `{$label_var1}`
- *[false] -> {""}
-} flows{$label_var2_exists ->
- [true] {" "}into `{$label_var2}`
- *[false] -> {""}
-} here
-
-infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
- [true] {" "}and update trait if needed
- *[false] {""}
-}
-infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
-
-infer_region_explanation = {$pref_kind ->
- *[should_not_happen] [{$pref_kind}]
- [ref_valid_for] ...the reference is valid for
- [content_valid_for] ...but the borrowed content is only valid for
- [type_obj_valid_for] object type is valid for
- [source_pointer_valid_for] source pointer is only valid for
- [type_satisfy] type must satisfy
- [type_outlive] type must outlive
- [lf_param_instantiated_with] lifetime parameter instantiated with
- [lf_param_must_outlive] but lifetime parameter must outlive
- [lf_instantiated_with] lifetime instantiated with
- [lf_must_outlive] but lifetime must outlive
- [pointer_valid_for] the pointer is valid for
- [data_valid_for] but the referenced data is only valid for
- [empty] {""}
-}{$pref_kind ->
- [empty] {""}
- *[other] {" "}
-}{$desc_kind ->
- *[should_not_happen] [{$desc_kind}]
- [restatic] the static lifetime
- [revar] lifetime {$desc_arg}
- [as_defined] the lifetime `{$desc_arg}` as defined here
- [as_defined_anon] the anonymous lifetime as defined here
- [defined_here] the anonymous lifetime defined here
- [defined_here_reg] the lifetime `{$desc_arg}` as defined here
-}{$suff_kind ->
- *[should_not_happen] [{$suff_kind}]
- [empty]{""}
- [continues] ...
- [req_by_binding] {" "}as required by this binding
-}
-
-infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
-infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
-infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
-infer_lf_bound_not_satisfied = lifetime bound not satisfied
-infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
-infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
-
-infer_mismatched_static_lifetime = incompatible lifetime on type
-infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
-infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
-infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
-infer_msl_introduces_static = introduces a `'static` lifetime requirement
-infer_msl_unmet_req = because this has an unmet lifetime requirement
-infer_msl_trait_note = this has an implicit `'static` lifetime requirement
-infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
-infer_suggest_add_let_for_letchains = consider adding `let`
-
-infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
- .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
- .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
-
-infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
-
-infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
-infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
-infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
- [true] ...
- *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`
-
-infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
+infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
-infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
+infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
@@ -260,26 +11,62 @@
*[false] {""}
}
-infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
- .label_satisfy = doesn't satisfy where-clause
- .label_where = due to a where-clause on `{$def_id}`...
- .label_dup = implementation of `{$trait_def_id}` is not general enough
+infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`
-infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
- .found = found `{$found}`
- .expected = expected `{$expected}`
- .expected_found = expected signature `{$expected}`
- {" "}found signature `{$found}`
+infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
+infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
+infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
+ [true] ...
+ *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
-infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
-infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+infer_await_both_futures = consider `await`ing on both `Future`s
+infer_await_future = consider `await`ing on the `Future`
+infer_await_note = calling an async function returns a future
-infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
-infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
-infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
-
+infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
infer_but_calling_introduces = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
@@ -314,6 +101,77 @@
.used_here = ...is used here...
.introduced_by_bound = `'static` lifetime requirement introduced by this bound
+infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
+infer_consider_specifying_length = consider specifying the actual array length
+infer_data_flows = ...but data{$label_var1_exists ->
+ [true] {" "}from `{$label_var1}`
+ *[false] -> {""}
+} flows{$label_var2_exists ->
+ [true] {" "}into `{$label_var2}`
+ *[false] -> {""}
+} here
+
+infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
+infer_data_returned = ...but data{$label_var1_exists ->
+ [true] {" "}from `{$label_var1}`
+ *[false] {""}
+} is returned here
+
+infer_declared_different = this parameter and the return type are declared with different lifetimes...
+infer_declared_multiple = this type is declared with multiple lifetimes...
+infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
+infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
+infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+
+infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
+
+infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
+
+infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
+ .label = lifetime `{$named}` required
+
+infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
+ .label = lifetime `{$named}` required
+
+infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+
+infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
+infer_fps_cast = consider casting to a fn pointer
+infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+
+infer_fps_items_are_distinct = fn items are distinct from fn pointers
+infer_fps_remove_ref = consider removing the reference
+infer_fps_use_ref = consider using a reference
+infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
+infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
+infer_label_bad = {$bad_kind ->
+ *[other] cannot infer type
+ [more_info] cannot infer {$prefix_kind ->
+ *[type] type for {$prefix}
+ [const_with_param] the value of const parameter
+ [const] the value of the constant
+ } `{$name}`{$has_parent ->
+ [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
+ *[false] {""}
+ }
+}
+
+infer_lf_bound_not_satisfied = lifetime bound not satisfied
+infer_lifetime_mismatch = lifetime mismatch
+
+infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
+ [true] {" "}and update trait if needed
+ *[false] {""}
+}
+infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
+
+infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
+infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
+infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
+infer_mismatched_static_lifetime = incompatible lifetime on type
infer_more_targeted = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
@@ -322,72 +180,215 @@
*[false] an anonymous lifetime `'_`
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
-infer_ril_introduced_here = `'static` requirement introduced here
-infer_ril_introduced_by = requirement introduced by this return type
-infer_ril_because_of = because of this returned expression
-infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
+infer_msl_introduces_static = introduces a `'static` lifetime requirement
+infer_msl_trait_note = this has an implicit `'static` lifetime requirement
+infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
+infer_msl_unmet_req = because this has an unmet lifetime requirement
+infer_need_type_info_in_generator =
+ type inside {$generator_kind ->
+ [async_block] `async` block
+ [async_closure] `async` closure
+ [async_fn] `async fn` body
+ *[generator] generator
+ } must be known in this context
-infer_where_remove = remove the `where` clause
-infer_where_copy_predicates = copy the `where` clause predicates from the trait
-infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
-infer_srs_remove = consider removing this semicolon
-infer_srs_add = consider returning the local binding `{$ident}`
-infer_srs_add_one = consider returning one of these bindings
+infer_nothing = {""}
-infer_await_both_futures = consider `await`ing on both `Future`s
-infer_await_future = consider `await`ing on the `Future`
-infer_await_note = calling an async function returns a future
+infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
+infer_oc_closure_selfref = closure/generator type that references itself
+infer_oc_const_compat = const not compatible with trait
+infer_oc_fn_main_correct_type = `main` function has wrong type
+infer_oc_fn_start_correct_type = `#[start]` function has wrong type
+infer_oc_generic = mismatched types
-infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
-infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
-infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
-
+infer_oc_if_else_different = `if` and `else` have incompatible types
+infer_oc_intrinsic_correct_type = intrinsic has wrong type
+infer_oc_match_compat = `match` arms have incompatible types
+infer_oc_method_compat = method not compatible with trait
+infer_oc_method_correct_type = mismatched `self` parameter type
+infer_oc_no_diverge = `else` clause of `let...else` does not diverge
+infer_oc_no_else = `if` may be missing an `else` clause
+infer_oc_try_compat = `?` operator has incompatible types
+infer_oc_type_compat = type not compatible with trait
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here
-infer_fps_use_ref = consider using a reference
-infer_fps_remove_ref = consider removing the reference
-infer_fps_cast = consider casting to a fn pointer
-infer_fps_items_are_distinct = fn items are distinct from fn pointers
-infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+infer_opaque_hidden_type =
+ opaque type's hidden type cannot be another opaque type from the same scope
+ .label = one of the two opaque types used here has to be outside its defining scope
+ .opaque_type = opaque type whose hidden type is being assigned
+ .hidden_type = opaque type being used as hidden type
-infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
-infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
+infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
+infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
+infer_prlf_defined_without_sub = the lifetime defined here...
+infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
+infer_reborrow = ...so that reference does not outlive borrowed content
+infer_reborrow_upvar = ...so that closure can access `{$name}`
+infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
+
+infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
+infer_region_explanation = {$pref_kind ->
+ *[should_not_happen] [{$pref_kind}]
+ [ref_valid_for] ...the reference is valid for
+ [content_valid_for] ...but the borrowed content is only valid for
+ [type_obj_valid_for] object type is valid for
+ [source_pointer_valid_for] source pointer is only valid for
+ [type_satisfy] type must satisfy
+ [type_outlive] type must outlive
+ [lf_param_instantiated_with] lifetime parameter instantiated with
+ [lf_param_must_outlive] but lifetime parameter must outlive
+ [lf_instantiated_with] lifetime instantiated with
+ [lf_must_outlive] but lifetime must outlive
+ [pointer_valid_for] the pointer is valid for
+ [data_valid_for] but the referenced data is only valid for
+ [empty] {""}
+}{$pref_kind ->
+ [empty] {""}
+ *[other] {" "}
+}{$desc_kind ->
+ *[should_not_happen] [{$desc_kind}]
+ [restatic] the static lifetime
+ [revar] lifetime {$desc_arg}
+ [as_defined] the lifetime `{$desc_arg}` as defined here
+ [as_defined_anon] the anonymous lifetime as defined here
+ [defined_here] the anonymous lifetime defined here
+ [defined_here_reg] the lifetime `{$desc_arg}` as defined here
+}{$suff_kind ->
+ *[should_not_happen] [{$suff_kind}]
+ [empty]{""}
+ [continues] ...
+ [req_by_binding] {" "}as required by this binding
+}
+
+infer_relate_object_bound = ...so that it can be closed over into an object
+infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
+ [true] ...
+ *[false] {""}
+}
+infer_relate_param_bound_2 = ...that is required by this bound
+infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
+infer_ril_because_of = because of this returned expression
+infer_ril_introduced_by = requirement introduced by this return type
+infer_ril_introduced_here = `'static` requirement introduced here
+infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
infer_sarwa_option = you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
infer_sarwa_result = you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
-infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
-
-infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
-infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
+infer_source_kind_closure_return =
+ try giving this closure an explicit return type
+
+# generator_kind may need to be translated
+infer_source_kind_fully_qualified =
+ try using a fully qualified path to specify the expected types
+
+infer_source_kind_subdiag_generic_label =
+ cannot infer {$is_type ->
+ [true] type
+ *[false] the value
+ } of the {$is_type ->
+ [true] type
+ *[false] const
+ } {$parent_exists ->
+ [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
+ *[false] parameter {$param_name}
+ }
+
+infer_source_kind_subdiag_generic_suggestion =
+ consider specifying the generic {$arg_count ->
+ [one] argument
+ *[other] arguments
+ }
+
+infer_source_kind_subdiag_let = {$kind ->
+ [with_pattern] consider giving `{$name}` an explicit type
+ [closure] consider giving this closure parameter an explicit type
+ *[other] consider giving this pattern a type
+}{$x_kind ->
+ [has_name] , where the {$prefix_kind ->
+ *[type] type for {$prefix}
+ [const_with_param] value of const parameter
+ [const] value of the constant
+ } `{$arg_name}` is specified
+ [underscore] , where the placeholders `_` are specified
+ *[empty] {""}
+}
+
+infer_srs_add = consider returning the local binding `{$ident}`
+infer_srs_add_one = consider returning one of these bindings
+
+infer_srs_remove = consider removing this semicolon
+infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
+infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_subtype = ...so that the {$requirement ->
+ [method_compat] method type is compatible with trait
+ [type_compat] associated type is compatible with trait
+ [const_compat] const is compatible with trait
+ [expr_assignable] expression is assignable
+ [if_else_different] `if` and `else` have incompatible types
+ [no_else] `if` missing an `else` returns `()`
+ [fn_main_correct_type] `main` function has the correct type
+ [fn_start_correct_type] `#[start]` function has the correct type
+ [intrinsic_correct_type] intrinsic has the correct type
+ [method_correct_type] method receiver has the correct type
+ *[other] types are compatible
+}
+infer_subtype_2 = ...so that {$requirement ->
+ [method_compat] method type is compatible with trait
+ [type_compat] associated type is compatible with trait
+ [const_compat] const is compatible with trait
+ [expr_assignable] expression is assignable
+ [if_else_different] `if` and `else` have incompatible types
+ [no_else] `if` missing an `else` returns `()`
+ [fn_main_correct_type] `main` function has the correct type
+ [fn_start_correct_type] `#[start]` function has the correct type
+ [intrinsic_correct_type] intrinsic has the correct type
+ [method_correct_type] method receiver has the correct type
+ *[other] types are compatible
+}
+
+infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+
+infer_suggest_add_let_for_letchains = consider adding `let`
+
+infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
+infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+
+infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
+ .found = found `{$found}`
+ .expected = expected `{$expected}`
+ .expected_found = expected signature `{$expected}`
+ {" "}found signature `{$found}`
+
+infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
+ .label_satisfy = doesn't satisfy where-clause
+ .label_where = due to a where-clause on `{$def_id}`...
+ .label_dup = implementation of `{$trait_def_id}` is not general enough
+
+infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+
infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
-infer_oc_method_compat = method not compatible with trait
-infer_oc_type_compat = type not compatible with trait
-infer_oc_const_compat = const not compatible with trait
-infer_oc_try_compat = `?` operator has incompatible types
-infer_oc_match_compat = `match` arms have incompatible types
-infer_oc_if_else_different = `if` and `else` have incompatible types
-infer_oc_no_else = `if` may be missing an `else` clause
-infer_oc_no_diverge = `else` clause of `let...else` does not diverge
-infer_oc_fn_main_correct_type = `main` function has wrong type
-infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_intrinsic_correct_type = intrinsic has wrong type
-infer_oc_method_correct_type = mismatched `self` parameter type
-infer_oc_closure_selfref = closure/generator type that references itself
-infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
-infer_oc_generic = mismatched types
+infer_type_annotations_needed = {$source_kind ->
+ [closure] type annotations needed for the closure `{$source_name}`
+ [normal] type annotations needed for `{$source_name}`
+ *[other] type annotations needed
+}
+ .label = type must be known at this point
-infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
-infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
-infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
-infer_consider_specifying_length = consider specifying the actual array length
-infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+infer_types_declared_different = these two types are declared with different lifetimes...
+infer_where_copy_predicates = copy the `where` clause predicates from the trait
+
+infer_where_remove = remove the `where` clause
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index de9afbb..88256c8 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -15,7 +15,7 @@
use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
-use crate::traits::query::{Fallible, NoSolution};
+use crate::traits::query::NoSolution;
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::captures::Captures;
@@ -57,7 +57,7 @@
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+ ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 79fc02c..b6b935d 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -113,10 +113,7 @@
bug!()
}
- (_, ty::Alias(AliasKind::Projection | AliasKind::Inherent, _))
- | (ty::Alias(AliasKind::Projection | AliasKind::Inherent, _), _)
- if self.tcx.trait_solver_next() =>
- {
+ (_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
relation.register_type_relate_obligation(a, b);
Ok(a)
}
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 793505e..42dfe4f6 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -104,7 +104,8 @@
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
- && def_id.is_local() =>
+ && def_id.is_local()
+ && !self.tcx().trait_solver_next() =>
{
self.fields.obligations.extend(
infcx
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ad4f505..35c05e8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1825,7 +1825,7 @@
s
};
if !(values.expected.is_simple_text() && values.found.is_simple_text())
- || (exp_found.map_or(false, |ef| {
+ || (exp_found.is_some_and(|ef| {
// This happens when the type error is a subset of the expectation,
// like when you have two references but one is `usize` and the other
// is `f32`. In those cases we still want to show the `note`. If the
@@ -1877,7 +1877,7 @@
let exp_found = match terr {
// `terr` has more accurate type information than `exp_found` in match expressions.
ty::error::TypeError::Sorts(terr)
- if exp_found.map_or(false, |ef| terr.found == ef.found) =>
+ if exp_found.is_some_and(|ef| terr.found == ef.found) =>
{
Some(terr)
}
@@ -1961,7 +1961,7 @@
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
&& !code.starts_with("\\u") // forbid all Unicode escapes
- && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
+ && code.chars().next().is_some_and(|c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
{
suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral { span, code: escape_literal(code) })
}
@@ -2329,7 +2329,7 @@
.source_map()
.span_to_prev_source(p.span.shrink_to_hi())
.ok()
- .map_or(false, |s| *s.as_bytes().last().unwrap() == b'&')
+ .is_some_and(|s| *s.as_bytes().last().unwrap() == b'&')
{
add_lt_suggs
.push(Some(
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 5000b01..f3b2ec4 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
@@ -671,7 +671,7 @@
receiver.span.from_expansion()
}
InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
- data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion)
+ data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
}
};
source_from_expansion || self.span.from_expansion()
@@ -984,7 +984,7 @@
) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
let tcx = self.infcx.tcx;
let have_turbofish = path.segments.iter().any(|segment| {
- segment.args.map_or(false, |args| args.args.iter().any(|arg| arg.is_ty_or_const()))
+ segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
});
// The last segment of a path often has `Res::Err` and the
// correct `Res` is the one of the whole path.
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 7f4c141..7190d33 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -108,9 +108,12 @@
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
- if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() =>
+ if this.define_opaque_types() == DefineOpaqueTypes::Yes
+ && def_id.is_local()
+ && !this.tcx().trait_solver_next() =>
{
this.register_obligations(
infcx
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f832996..cd99fc3 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -24,7 +24,7 @@
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::select;
+use rustc_middle::traits::{select, DefiningAnchor};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -231,17 +231,6 @@
}
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum DefiningAnchor {
- /// `DefId` of the item.
- Bind(LocalDefId),
- /// When opaque types are not resolved, we `Bubble` up, meaning
- /// return the opaque/hidden type pair from query, for caller of query to handle it.
- Bubble,
- /// Used to catch type mismatch errors when handling opaque types.
- Error,
-}
-
pub struct InferCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 4ae6af5..d3fd01b 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -491,16 +491,22 @@
(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
- ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
- self.tcx().sess.delay_span_bug(
- self.delegate.span(),
- "failure to relate an opaque to itself should result in an error later on",
- );
- if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
- }),
+ ) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
+ infcx.super_combine_tys(self, a, b).or_else(|err| {
+ // This behavior is only there for the old solver, the new solver
+ // shouldn't ever fail. Instead, it unconditionally emits an
+ // alias-relate goal.
+ assert!(!self.tcx().trait_solver_next());
+ self.tcx().sess.delay_span_bug(
+ self.delegate.span(),
+ "failure to relate an opaque to itself should result in an error later on",
+ );
+ if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+ })
+ }
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
- if def_id.is_local() =>
+ if def_id.is_local() && !self.tcx().trait_solver_next() =>
{
self.relate_opaques(a, b)
}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index b88ba04..9d5ec22 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,14 +1,14 @@
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::{DefineOpaqueTypes, InferResult};
use crate::errors::OpaqueHiddenTypeDiag;
-use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
-use crate::traits;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::{self, PredicateObligation};
use hir::def_id::{DefId, LocalDefId};
use hir::OpaqueTyOrigin;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
-use rustc_middle::traits::ObligationCause;
+use rustc_middle::traits::{DefiningAnchor, ObligationCause};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::GenericArgKind;
@@ -48,12 +48,18 @@
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, T> {
+ // We handle opaque types differently in the new solver.
+ if self.tcx.trait_solver_next() {
+ return InferOk { value, obligations: vec![] };
+ }
+
if !value.has_opaque_types() {
return InferOk { value, obligations: vec![] };
}
+
let mut obligations = vec![];
let replace_opaque_type = |def_id: DefId| {
- def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some())
+ def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
};
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx,
@@ -521,9 +527,6 @@
origin: hir::OpaqueTyOrigin,
a_is_expected: bool,
) -> InferResult<'tcx, ()> {
- let tcx = self.tcx;
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
// Ideally, we'd get the span where *this specific `ty` came
// from*, but right now we just use the span from the overall
// value being folded. In simple cases like `-> impl Foo`,
@@ -531,7 +534,7 @@
// Foo, impl Bar)`.
let span = cause.span;
let prev = self.inner.borrow_mut().opaque_types().register(
- OpaqueTypeKey { def_id, substs },
+ opaque_type_key,
OpaqueHiddenType { ty: hidden_ty, span },
origin,
);
@@ -543,6 +546,49 @@
Vec::new()
};
+ self.add_item_bounds_for_hidden_type(
+ opaque_type_key,
+ cause,
+ param_env,
+ hidden_ty,
+ &mut obligations,
+ );
+
+ Ok(InferOk { value: (), obligations })
+ }
+
+ /// Registers an opaque's hidden type -- only should be used when the opaque
+ /// can be defined. For something more fallible -- checks the anchors, tries
+ /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
+ pub fn register_hidden_type_in_new_solver(
+ &self,
+ opaque_type_key: OpaqueTypeKey<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ hidden_ty: Ty<'tcx>,
+ ) -> InferResult<'tcx, ()> {
+ assert!(self.tcx.trait_solver_next());
+ let origin = self
+ .opaque_type_origin(opaque_type_key.def_id)
+ .expect("should be called for defining usages only");
+ self.register_hidden_type(
+ opaque_type_key,
+ ObligationCause::dummy(),
+ param_env,
+ hidden_ty,
+ origin,
+ true,
+ )
+ }
+
+ pub fn add_item_bounds_for_hidden_type(
+ &self,
+ OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
+ cause: ObligationCause<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ hidden_ty: Ty<'tcx>,
+ obligations: &mut Vec<PredicateObligation<'tcx>>,
+ ) {
+ let tcx = self.tcx;
let item_bounds = tcx.explicit_item_bounds(def_id);
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
@@ -555,14 +601,15 @@
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
ty::Alias(ty::Projection, projection_ty)
if !projection_ty.has_escaping_bound_vars()
- && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
+ && !tcx.is_impl_trait_in_trait(projection_ty.def_id)
+ && !tcx.trait_solver_next() =>
{
self.infer_projection(
param_env,
projection_ty,
cause.clone(),
0,
- &mut obligations,
+ obligations,
)
}
// Replace all other mentions of the same opaque type with the hidden type,
@@ -588,10 +635,10 @@
predicate.kind().skip_binder()
{
if projection.term.references_error() {
- // No point on adding these obligations since there's a type error involved.
- return Ok(InferOk { value: (), obligations: vec![] });
+ // No point on adding any obligations since there's a type error involved.
+ obligations.clear();
+ return;
}
- trace!("{:#?}", projection.term);
}
// Require that the predicate holds for the concrete type.
debug!(?predicate);
@@ -602,7 +649,6 @@
predicate,
));
}
- Ok(InferOk { value: (), obligations })
}
}
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index e0f29a8..ceafafb 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -131,7 +131,8 @@
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
- && def_id.is_local() =>
+ && def_id.is_local()
+ && !self.tcx().trait_solver_next() =>
{
self.fields.obligations.extend(
infcx
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 3799489..be1a75f 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -1,9 +1,28 @@
+interface_cant_emit_mir =
+ could not emit MIR: {$error}
+
+interface_emoji_identifier =
+ identifiers cannot contain emoji: `{$ident}`
+
+interface_error_writing_dependencies =
+ error writing dependencies to `{$path}`: {$error}
+
+interface_failed_writing_file =
+ failed to write file {$path}: {$error}"
+
interface_ferris_identifier =
Ferris cannot be used as an identifier
.suggestion = try using their name instead
-interface_emoji_identifier =
- identifiers cannot contain emoji: `{$ident}`
+interface_generated_file_conflicts_with_directory =
+ the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
+
+interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
+
+interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
+
+interface_input_file_would_be_overwritten =
+ the input file "{$path}" would be overwritten by the generated executable
interface_mixed_bin_crate =
cannot mix `bin` crate type with others
@@ -11,23 +30,14 @@
interface_mixed_proc_macro_crate =
cannot mix `proc-macro` crate type with others
-interface_error_writing_dependencies =
- error writing dependencies to `{$path}`: {$error}
-
-interface_input_file_would_be_overwritten =
- the input file "{$path}" would be overwritten by the generated executable
-
-interface_generated_file_conflicts_with_directory =
- the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
-
-interface_temps_dir_error =
- failed to find or create the directory specified by `--temps-dir`
+interface_multiple_output_types_adaption =
+ due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
interface_out_dir_error =
failed to find or create the directory specified by `--out-dir`
-interface_cant_emit_mir =
- could not emit MIR: {$error}
+interface_proc_macro_crate_panic_abort =
+ building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
interface_rustc_error_fatal =
fatal error triggered by #[rustc_error]
@@ -35,18 +45,8 @@
interface_rustc_error_unexpected_annotation =
unexpected annotation used with `#[rustc_error(...)]`!
-interface_failed_writing_file =
- failed to write file {$path}: {$error}"
-
-interface_proc_macro_crate_panic_abort =
- building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+interface_temps_dir_error =
+ failed to find or create the directory specified by `--temps-dir`
interface_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
-
-interface_multiple_output_types_adaption =
- due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
-
-interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
-
-interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 6818197..39d5689 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -3,9 +3,9 @@
use rustc_ast::token;
use rustc_ast::{self as ast, LitKind, MetaItemKind};
use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_data_structures::defer;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::OnDrop;
use rustc_errors::registry::Registry;
use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_lint::LintStore;
@@ -325,7 +325,7 @@
rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
let r = {
- let _sess_abort_error = OnDrop(|| {
+ let _sess_abort_error = defer(|| {
compiler.sess.finish_diagnostics(registry);
});
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index e1658d3..d34a3af 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -5,6 +5,202 @@
.use_explicit_into_iter_suggestion =
or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
+lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
+ .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+
+lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
+ .label = invalid failure ordering
+ .help = consider using `Acquire` or `Relaxed` failure ordering instead
+
+lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
+ .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+
+lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
+ .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
+
+lint_bad_attribute_argument = bad attribute argument
+
+lint_bad_opt_access = {$msg}
+
+lint_builtin_allow_internal_unsafe =
+ `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
+
+lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
+ .suggestion = try naming the parameter or explicitly ignoring it
+
+lint_builtin_asm_labels = avoid using named labels in inline assembly
+
+lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
+
+lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
+ .previous_decl_label = `{$orig}` previously declared here
+ .mismatch_label = this signature doesn't match the previous declaration
+
+lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
+ .previous_decl_label = `{$orig}` previously declared here
+ .mismatch_label = this signature doesn't match the previous declaration
+lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
+ .suggestion = try a static value
+
+lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
+lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
+lint_builtin_deprecated_attr_default_suggestion = remove this attribute
+
+lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
+ .msg_suggestion = {$msg}
+ .default_suggestion = remove this attribute
+lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
+lint_builtin_deref_nullptr = dereferencing a null pointer
+ .label = this code causes undefined behavior when executed
+
+lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
+ .suggestion = use `..=` for an inclusive range
+
+lint_builtin_explicit_outlives = outlives requirements can be inferred
+ .suggestion = remove {$count ->
+ [one] this bound
+ *[other] these bounds
+ }
+
+lint_builtin_export_name_fn = declaration of a function with `export_name`
+lint_builtin_export_name_method = declaration of a method with `export_name`
+
+lint_builtin_export_name_static = declaration of a static with `export_name`
+lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
+
+lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
+ .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
+ .help = consider using `min_{$name}` instead, which is more stable and complete
+
+lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
+ .suggestion = you can use a raw identifier to stay compatible
+
+lint_builtin_link_section_fn = declaration of a function with `link_section`
+
+lint_builtin_link_section_static = declaration of a static with `link_section`
+
+lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
+
+lint_builtin_missing_debug_impl =
+ type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
+
+lint_builtin_missing_doc = missing documentation for {$article} {$desc}
+
+lint_builtin_mutable_transmutes =
+ transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+
+lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
+lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
+ .suggestion = remove this attribute
+
+lint_builtin_no_mangle_method = declaration of a `no_mangle` method
+lint_builtin_no_mangle_static = declaration of a `no_mangle` static
+lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
+ .suggestion = use shorthand field pattern
+
+lint_builtin_overridden_symbol_name =
+ the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_overridden_symbol_section =
+ the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
+ .note = lib.rs is the root of this crate's library target
+ .help = to refer to it from other targets, use the library's name as the path
+
+lint_builtin_special_module_name_used_main = found module declaration for main.rs
+ .note = a binary crate cannot be used as library
+
+lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
+
+lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+
+lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
+ .suggestion = the bound will not be checked when the type alias is used, and should be removed
+
+lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
+ .suggestion = the clause will not be checked when the type alias is used, and should be removed
+
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+lint_builtin_unnameable_test_items = cannot test inner items
+
+lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
+lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+
+lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
+
+lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
+lint_builtin_unreachable_pub = unreachable `pub` {$what}
+ .suggestion = consider restricting its visibility
+ .help = or consider exporting it for use by other crates
+
+lint_builtin_unsafe_block = usage of an `unsafe` block
+
+lint_builtin_unsafe_impl = implementation of an `unsafe` trait
+
+lint_builtin_unsafe_trait = declaration of an `unsafe` trait
+
+lint_builtin_unstable_features = unstable feature
+
+lint_builtin_unused_doc_comment = unused doc comment
+ .label = rustdoc does not generate documentation for {$kind}
+ .plain_help = use `//` for a plain comment
+ .block_help = use `/* */` for a plain comment
+
+lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
+ .suggestion = use `loop`
+
+lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
+
+lint_check_name_unknown = unknown lint: `{$lint_name}`
+ .help = did you mean: `{$suggestion}`
+
+lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
+
+lint_check_name_warning = {$msg}
+
+lint_command_line_source = `forbid` lint level was set on command line
+
+lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
+ .label = this is where the previous identifier occurred
+
+lint_cstring_ptr = getting the inner pointer of a temporary `CString`
+ .as_ptr_label = this pointer will be invalid
+ .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
+ .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
+ .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
+
+lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
+ .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
+
+lint_default_source = `forbid` lint level is the default for {$id}
+
+lint_deprecated_lint_name =
+ lint name `{$name}` is deprecated and may not have an effect in the future.
+ .suggestion = change it to
+
+lint_diag_out_of_impl =
+ diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+
+lint_drop_glue =
+ types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
+
+lint_drop_trait_constraints =
+ bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
+
+lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
+ .label = argument has type `{$arg_ty}`
+ .note = use `let _ = ...` to ignore the expression or result
+
+lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
+ .label = argument has type `{$arg_ty}`
+ .note = use `let _ = ...` to ignore the expression or result
+
lint_enum_intrinsics_mem_discriminant =
the return value of `mem::discriminant` is unspecified when called with a non-enum type
.note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum.
@@ -24,49 +220,12 @@
.use_while_let = to check pattern in a loop use `while let`
.use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
-lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
- .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
- .function_label = this function returns `()`, which is likely not what you wanted
- .argument_label = called `Iterator::map` with callable that returns `()`
- .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
- .suggestion = you might have meant to use `Iterator::for_each`
-
-lint_non_binding_let_on_sync_lock =
- non-binding let on a synchronization lock
-
-lint_non_binding_let_on_drop_type =
- non-binding let on a type that implements `Drop`
-
-lint_non_binding_let_suggestion =
- consider binding to an unused variable to avoid immediately dropping the value
-
-lint_non_binding_let_multi_suggestion =
- consider immediately dropping the value
-
-lint_deprecated_lint_name =
- lint name `{$name}` is deprecated and may not have an effect in the future.
- .suggestion = change it to
-
-lint_renamed_or_removed_lint = {$msg}
- .suggestion = use the new name
-
-lint_suspicious_double_ref_op =
- using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
- *[should_not_happen] [{$op}]
- [deref] dereferencing
- [borrow] borrowing
- [clone] cloning
- } the inner type
-
-lint_unknown_lint =
- unknown lint: `{$name}`
- .suggestion = did you mean
-
-lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
-
-lint_unknown_gated_lint =
- unknown lint: `{$name}`
- .note = the `{$name}` lint is unstable
+lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
+ .label = argument has type `{$arg_ty}`
+ .note = use `let _ = ...` to ignore the expression or result
+lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
+ .label = argument has type `{$arg_ty}`
+ .note = use `let _ = ...` to ignore the expression or result
lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
.label = this {$label} contains {$count ->
@@ -81,56 +240,111 @@
.suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them
.no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped}
-lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
- .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
-
-lint_query_instability = using `{$query}` can result in unstable query results
- .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-lint_tykind_kind = usage of `ty::TyKind::<kind>`
- .suggestion = try using `ty::<kind>` directly
-
-lint_tykind = usage of `ty::TyKind`
- .help = try using `Ty` instead
-
-lint_ty_qualified = usage of qualified `ty::{$ty}`
- .suggestion = try importing it and using it unqualified
-
-lint_lintpass_by_hand = implementing `LintPass` by hand
- .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
-
-lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
- .help = only existing keywords are allowed in core/std
-
-lint_diag_out_of_impl =
- diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
-
-lint_untranslatable_diag = diagnostics should be created using translatable messages
-
-lint_trivial_untranslatable_diag = diagnostic with static strings only
-
-lint_bad_opt_access = {$msg}
-
-lint_cstring_ptr = getting the inner pointer of a temporary `CString`
- .as_ptr_label = this pointer will be invalid
- .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
- .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
- .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
-
-lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
-
lint_identifier_non_ascii_char = identifier contains non-ASCII characters
lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
-lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
- .label = this is where the previous identifier occurred
+lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
+
+lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
+ .label = not FFI-safe
+ .note = the type is defined here
+
+lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+
+lint_improper_ctypes_array_help = consider passing a pointer to the array
+
+lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
+lint_improper_ctypes_box = box cannot be represented as a single pointer
+
+lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+
+lint_improper_ctypes_char_reason = the `char` type has no C equivalent
+lint_improper_ctypes_dyn = trait objects have no C equivalent
+
+lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+
+lint_improper_ctypes_enum_repr_help =
+ consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+
+lint_improper_ctypes_enum_repr_reason = enum has no representation hint
+lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+
+lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
+lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
+lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
+
+lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+
+lint_improper_ctypes_opaque = opaque types have no C equivalent
+
+lint_improper_ctypes_slice_help = consider using a raw pointer instead
+
+lint_improper_ctypes_slice_reason = slices have no C equivalent
+lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+
+lint_improper_ctypes_str_reason = string slices have no C equivalent
+lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+
+lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
+lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+
+lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
+lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
+lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+
+lint_improper_ctypes_tuple_help = consider using a struct instead
+
+lint_improper_ctypes_tuple_reason = tuples have unspecified layout
+lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+
+lint_improper_ctypes_union_fieldless_reason = this union has no fields
+lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+
+lint_improper_ctypes_union_layout_reason = this union has unspecified layout
+lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+
+lint_lintpass_by_hand = implementing `LintPass` by hand
+ .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+lint_malformed_attribute = malformed lint attribute input
+
+lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
+ .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+ .function_label = this function returns `()`, which is likely not what you wanted
+ .argument_label = called `Iterator::map` with callable that returns `()`
+ .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ .suggestion = you might have meant to use `Iterator::for_each`
lint_mixed_script_confusables =
the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
.includes_note = the usage includes {$includes}
.note = please recheck to make sure their usages are indeed what you want
+lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+
+lint_node_source = `forbid` level set here
+ .note = {$reason}
+
+lint_non_binding_let_multi_suggestion =
+ consider immediately dropping the value
+
+lint_non_binding_let_on_drop_type =
+ non-binding let on a type that implements `Drop`
+
+lint_non_binding_let_on_sync_lock =
+ non-binding let on a synchronization lock
+
+lint_non_binding_let_suggestion =
+ consider binding to an unused variable to avoid immediately dropping the value
+
+lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
+ .suggestion = convert the identifier to upper camel case
+ .label = should have an UpperCamelCase name
+
+lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
+ .help = only existing keywords are allowed in core/std
+
lint_non_fmt_panic = panic message is not a string literal
.note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
.more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
@@ -144,6 +358,14 @@
*[false] use
} std::panic::panic_any instead
+lint_non_fmt_panic_braces =
+ panic message contains {$count ->
+ [one] a brace
+ *[other] braces
+ }
+ .note = this message is not used as a format string, but will be in Rust 2021
+ .suggestion = add a "{"{"}{"}"}" format string to use the message literally
+
lint_non_fmt_panic_unused =
panic message contains {$count ->
[one] an unused
@@ -159,18 +381,6 @@
}
.add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
-lint_non_fmt_panic_braces =
- panic message contains {$count ->
- [one] a brace
- *[other] braces
- }
- .note = this message is not used as a format string, but will be in Rust 2021
- .suggestion = add a "{"{"}{"}"}" format string to use the message literally
-
-lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
- .suggestion = convert the identifier to upper camel case
- .label = should have an UpperCamelCase name
-
lint_non_snake_case = {$sort} `{$name}` should have a snake case name
.rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier
.cannot_convert_note = `{$sc}` cannot be used as a raw identifier
@@ -187,29 +397,13 @@
.label = unnecessary method call
.note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed
-lint_pass_by_value = passing `{$ty}` by reference
- .suggestion = try passing by value
+lint_only_cast_u8_to_char = only `u8` can be cast into `char`
+ .suggestion = use a `char` literal instead
-lint_redundant_semicolons =
- unnecessary trailing {$multiple ->
- [true] semicolons
- *[false] semicolon
- }
- .suggestion = remove {$multiple ->
- [true] these semicolons
- *[false] this semicolon
- }
+lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
+ .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
-lint_drop_trait_constraints =
- bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
-
-lint_drop_glue =
- types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
-
-lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
-
-lint_range_use_inclusive_range = use an inclusive range instead
-
+lint_opaque_hidden_inferred_bound_sugg = add this bound
lint_overflowing_bin_hex = literal out of range for `{$ty}`
.negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
@@ -222,96 +416,92 @@
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
.help = consider using the type `{$suggestion_ty}` instead
-lint_only_cast_u8_to_char = only `u8` can be cast into `char`
- .suggestion = use a `char` literal instead
+lint_overflowing_literal = literal out of range for `{$ty}`
+ .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
lint_overflowing_uint = literal out of range for `{$ty}`
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
-lint_overflowing_literal = literal out of range for `{$ty}`
- .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
+lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
+ .label = overruled by previous forbid
-lint_unused_comparisons = comparison is useless due to type limits
+lint_pass_by_value = passing `{$ty}` by reference
+ .suggestion = try passing by value
-lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
- .label = not FFI-safe
- .note = the type is defined here
+lint_path_statement_drop = path statement drops value
+ .suggestion = use `drop` to clarify the intent
-lint_improper_ctypes_opaque = opaque types have no C equivalent
+lint_path_statement_no_effect = path statement with no effect
-lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
-lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+lint_query_instability = using `{$query}` can result in unstable query results
+ .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-lint_improper_ctypes_tuple_reason = tuples have unspecified layout
-lint_improper_ctypes_tuple_help = consider using a struct instead
+lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
-lint_improper_ctypes_str_reason = string slices have no C equivalent
-lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+lint_range_use_inclusive_range = use an inclusive range instead
-lint_improper_ctypes_dyn = trait objects have no C equivalent
-lint_improper_ctypes_slice_reason = slices have no C equivalent
-lint_improper_ctypes_slice_help = consider using a raw pointer instead
+lint_reason_must_be_string_literal = reason must be a string literal
-lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+lint_reason_must_come_last = reason in lint attribute must come last
-lint_improper_ctypes_char_reason = the `char` type has no C equivalent
-lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+lint_redundant_semicolons =
+ unnecessary trailing {$multiple ->
+ [true] semicolons
+ *[false] semicolon
+ }
+ .suggestion = remove {$multiple ->
+ [true] these semicolons
+ *[false] this semicolon
+ }
-lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
-lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
+lint_renamed_or_removed_lint = {$msg}
+ .suggestion = use the new name
-lint_improper_ctypes_enum_repr_reason = enum has no representation hint
-lint_improper_ctypes_enum_repr_help =
- consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+lint_requested_level = requested on the command line with `{$level} {$lint_name}`
-lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
-lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
+ .label = target type is set here
-lint_improper_ctypes_union_fieldless_reason = this union has no fields
-lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+lint_suspicious_double_ref_op =
+ using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
+ *[should_not_happen] [{$op}]
+ [deref] dereferencing
+ [borrow] borrowing
+ [clone] cloning
+ } the inner type
-lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
-lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+lint_trivial_untranslatable_diag = diagnostic with static strings only
-lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
-lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+lint_ty_qualified = usage of qualified `ty::{$ty}`
+ .suggestion = try importing it and using it unqualified
-lint_improper_ctypes_union_layout_reason = this union has unspecified layout
-lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+lint_tykind = usage of `ty::TyKind`
+ .help = try using `Ty` instead
-lint_improper_ctypes_box = box cannot be represented as a single pointer
+lint_tykind_kind = usage of `ty::TyKind::<kind>`
+ .suggestion = try using `ty::<kind>` directly
-lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
+ .label = this function will not propagate the caller location
-lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+lint_unknown_gated_lint =
+ unknown lint: `{$name}`
+ .note = the `{$name}` lint is unstable
-lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
-lint_improper_ctypes_array_help = consider passing a pointer to the array
+lint_unknown_lint =
+ unknown lint: `{$name}`
+ .suggestion = did you mean
-lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
+ .help = add `#![register_tool({$tool_name})]` to the crate root
-lint_variant_size_differences =
- enum variant is more than three times larger ({$largest} bytes) than the next largest
+lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
-lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
- .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+lint_untranslatable_diag = diagnostics should be created using translatable messages
-lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
- .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
-
-lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
- .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
-
-lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
- .label = invalid failure ordering
- .help = consider using `Acquire` or `Relaxed` failure ordering instead
-
-lint_unused_op = unused {$op} that must be used
- .label = the {$op} produces a value
- .suggestion = use `let _ = ...` to ignore the resulting value
-
-lint_unused_result = unused result of type `{$ty}`
+lint_unused_allocation = unnecessary allocation, use `&` instead
+lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
lint_unused_closure =
unused {$pre}{$count ->
@@ -320,6 +510,14 @@
}{$post} that must be used
.note = closures are lazy and do nothing unless called
+lint_unused_comparisons = comparison is useless due to type limits
+
+lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
+ .suggestion = use `let _ = ...` to ignore the resulting value
+
+lint_unused_delim = unnecessary {$delim} around {$item}
+ .suggestion = remove these {$delim}
+
lint_unused_generator =
unused {$pre}{$count ->
[one] generator
@@ -327,212 +525,13 @@
}{$post} that must be used
.note = generators are lazy and do nothing unless resumed
-lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
- .suggestion = use `let _ = ...` to ignore the resulting value
-
-lint_path_statement_drop = path statement drops value
- .suggestion = use `drop` to clarify the intent
-
-lint_path_statement_no_effect = path statement with no effect
-
-lint_unused_delim = unnecessary {$delim} around {$item}
- .suggestion = remove these {$delim}
-
lint_unused_import_braces = braces around {$node} is unnecessary
-lint_unused_allocation = unnecessary allocation, use `&` instead
-lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
+lint_unused_op = unused {$op} that must be used
+ .label = the {$op} produces a value
+ .suggestion = use `let _ = ...` to ignore the resulting value
-lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
- .suggestion = use `loop`
+lint_unused_result = unused result of type `{$ty}`
-lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
-
-lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
- .suggestion = use shorthand field pattern
-
-lint_builtin_overridden_symbol_name =
- the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_overridden_symbol_section =
- the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_allow_internal_unsafe =
- `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
-
-lint_builtin_unsafe_block = usage of an `unsafe` block
-
-lint_builtin_unsafe_trait = declaration of an `unsafe` trait
-
-lint_builtin_unsafe_impl = implementation of an `unsafe` trait
-
-lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
-lint_builtin_export_name_fn = declaration of a function with `export_name`
-lint_builtin_link_section_fn = declaration of a function with `link_section`
-
-lint_builtin_no_mangle_static = declaration of a `no_mangle` static
-lint_builtin_export_name_static = declaration of a static with `export_name`
-lint_builtin_link_section_static = declaration of a static with `link_section`
-
-lint_builtin_no_mangle_method = declaration of a `no_mangle` method
-lint_builtin_export_name_method = declaration of a method with `export_name`
-
-lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
-lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
-lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
-
-lint_builtin_missing_doc = missing documentation for {$article} {$desc}
-
-lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
-
-lint_builtin_missing_debug_impl =
- type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
-
-lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
- .suggestion = try naming the parameter or explicitly ignoring it
-
-lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
- .msg_suggestion = {$msg}
- .default_suggestion = remove this attribute
-lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
-lint_builtin_deprecated_attr_default_suggestion = remove this attribute
-
-lint_builtin_unused_doc_comment = unused doc comment
- .label = rustdoc does not generate documentation for {$kind}
- .plain_help = use `//` for a plain comment
- .block_help = use `/* */` for a plain comment
-
-lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
- .suggestion = remove this attribute
-
-lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
- .suggestion = try a static value
-
-lint_builtin_mutable_transmutes =
- transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
-
-lint_builtin_unstable_features = unstable feature
-
-lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
- .label = this function will not propagate the caller location
-
-lint_builtin_unreachable_pub = unreachable `pub` {$what}
- .suggestion = consider restricting its visibility
- .help = or consider exporting it for use by other crates
-
-lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
- .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
-
-lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
- .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
-
-lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-
-lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
- .suggestion = the clause will not be checked when the type alias is used, and should be removed
-
-lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
- .suggestion = the bound will not be checked when the type alias is used, and should be removed
-
-lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
-
-lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
- .suggestion = use `..=` for an inclusive range
-
-lint_builtin_unnameable_test_items = cannot test inner items
-
-lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
- .suggestion = you can use a raw identifier to stay compatible
-
-lint_builtin_explicit_outlives = outlives requirements can be inferred
- .suggestion = remove {$count ->
- [one] this bound
- *[other] these bounds
- }
-
-lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
- .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
- .help = consider using `min_{$name}` instead, which is more stable and complete
-
-lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
-lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
-
-lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
-lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
-
-lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
- .previous_decl_label = `{$orig}` previously declared here
- .mismatch_label = this signature doesn't match the previous declaration
-lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
- .previous_decl_label = `{$orig}` previously declared here
- .mismatch_label = this signature doesn't match the previous declaration
-
-lint_builtin_deref_nullptr = dereferencing a null pointer
- .label = this code causes undefined behavior when executed
-
-lint_builtin_asm_labels = avoid using named labels in inline assembly
-
-lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
- .note = lib.rs is the root of this crate's library target
- .help = to refer to it from other targets, use the library's name as the path
-
-lint_builtin_special_module_name_used_main = found module declaration for main.rs
- .note = a binary crate cannot be used as library
-
-lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
- .label = target type is set here
-
-lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
- .label = overruled by previous forbid
-
-lint_default_source = `forbid` lint level is the default for {$id}
-
-lint_node_source = `forbid` level set here
- .note = {$reason}
-
-lint_command_line_source = `forbid` lint level was set on command line
-
-lint_malformed_attribute = malformed lint attribute input
-
-lint_bad_attribute_argument = bad attribute argument
-
-lint_reason_must_be_string_literal = reason must be a string literal
-
-lint_reason_must_come_last = reason in lint attribute must come last
-
-lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
- .help = add `#![register_tool({$tool_name})]` to the crate root
-
-lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
-
-lint_requested_level = requested on the command line with `{$level} {$lint_name}`
-
-lint_check_name_unknown = unknown lint: `{$lint_name}`
- .help = did you mean: `{$suggestion}`
-
-lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
-
-lint_check_name_warning = {$msg}
-
-lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
-
-lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
- .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
-
-lint_opaque_hidden_inferred_bound_sugg = add this bound
-
-lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
- .label = argument has type `{$arg_ty}`
- .note = use `let _ = ...` to ignore the expression or result
-
-lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
- .label = argument has type `{$arg_ty}`
- .note = use `let _ = ...` to ignore the expression or result
-
-lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
- .label = argument has type `{$arg_ty}`
- .note = use `let _ = ...` to ignore the expression or result
-
-lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
- .label = argument has type `{$arg_ty}`
- .note = use `let _ = ...` to ignore the expression or result
+lint_variant_size_differences =
+ enum variant is more than three times larger ({$largest} bytes) than the next largest
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 6601a80..358d412 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -961,7 +961,7 @@
Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
}
- if attrs.peek().map_or(false, |next_attr| next_attr.is_doc_comment()) {
+ if attrs.peek().is_some_and(|next_attr| next_attr.is_doc_comment()) {
continue;
}
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 0082aaa..6f773e0 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -383,9 +383,8 @@
debug!(?span, ?def_id, ?substs);
let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
.ok()
- .and_then(|inst| inst)
- .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
- .unwrap_or(false);
+ .flatten()
+ .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics));
if !has_attr {
return;
}
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index c9781a7..8a4a451 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -240,8 +240,10 @@
}
fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
- lint_callback!(self, check_arm, a);
- hir_visit::walk_arm(self, a);
+ self.with_lint_attrs(a.hir_id, |cx| {
+ lint_callback!(cx, check_arm, a);
+ hir_visit::walk_arm(cx, a);
+ })
}
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index b92ed11f..8376835 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -242,7 +242,9 @@
struct QueryMapExpectationsWrapper<'tcx> {
tcx: TyCtxt<'tcx>,
+ /// HirId of the currently investigated element.
cur: HirId,
+ /// Level map for `cur`.
specs: ShallowLintLevelMap,
expectations: Vec<(LintExpectationId, LintExpectation)>,
unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>,
@@ -255,11 +257,11 @@
self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
}
fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
- let specs = self.specs.specs.get_mut_or_insert_default(self.cur.local_id);
- specs.clear();
- specs.insert(id, lvl);
+ self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl);
}
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
+ // We cannot use `tcx.lint_level_at_node` because we want to know in which order the
+ // attributes have been inserted, in particular whether an `expect` follows a `forbid`.
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
}
fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
@@ -355,7 +357,9 @@
impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
fn add_id(&mut self, hir_id: HirId) {
+ // Change both the `HirId` and the associated specs.
self.provider.cur = hir_id;
+ self.provider.specs.specs.clear();
self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id));
}
}
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 5bb1abf..b218cc5 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -128,7 +128,7 @@
// No clue where this argument is coming from.
return lint;
}
- if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
+ if arg_macro.is_some_and(|id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
// A case of `panic!(format!(..))`.
lint.note(fluent::lint_supports_fmt_note);
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 125b4dc..4bf4fda 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -677,7 +677,7 @@
let param_env = tcx.param_env(variant.def_id);
variant.fields.iter().find(|field| {
let field_ty = tcx.type_of(field.did).subst_identity();
- let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
+ let is_zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_zst());
!is_zst
})
}
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 0fe140e..8f75fa1 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -664,8 +664,8 @@
_ => return,
};
let keep_space = (
- left_pos.map_or(false, |s| s >= value.span.lo()),
- right_pos.map_or(false, |s| s <= value.span.hi()),
+ left_pos.is_some_and(|s| s >= value.span.lo()),
+ right_pos.is_some_and(|s| s <= value.span.hi()),
);
self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
}
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 79b8b41..6d8601b 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,131 +1,58 @@
-metadata_rlib_required =
- crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+metadata_as_needed_compatibility =
+ linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
-metadata_lib_required =
- crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+metadata_bad_panic_strategy =
+ the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
-metadata_rustc_lib_required =
- crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
- .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
- .help = try adding `extern crate rustc_driver;` at the top level of this crate
+metadata_bundle_needs_static =
+ linking modifier `bundle` is only compatible with `static` linking kind
+
+metadata_cannot_find_crate =
+ can't find crate for `{$crate_name}`{$add_info}
+
+metadata_cant_find_crate =
+ can't find crate
+
+metadata_compiler_missing_profiler =
+ the compiler may have been built without the profiler runtime
+
+metadata_conflicting_alloc_error_handler =
+ the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
+
+metadata_conflicting_global_alloc =
+ the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+
+metadata_consider_building_std =
+ consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_consider_downloading_target =
+ consider downloading the target with `rustup target add {$locator_triple}`
metadata_crate_dep_multiple =
cannot satisfy dependencies so `{$crate_name}` only shows up once
.help = having upstream crates all available in one format will likely make this go away
-metadata_two_panic_runtimes =
- cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+metadata_crate_location_unknown_type =
+ extern location for {$crate_name} is of an unknown type: {$path}
-metadata_bad_panic_strategy =
- the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+metadata_crate_not_panic_runtime =
+ the crate `{$crate_name}` is not a panic runtime
-metadata_required_panic_strategy =
- the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
-
-metadata_incompatible_panic_in_drop_strategy =
- the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
-
-metadata_multiple_names_in_link =
- multiple `name` arguments in a single `#[link]` attribute
-
-metadata_multiple_kinds_in_link =
- multiple `kind` arguments in a single `#[link]` attribute
-
-metadata_link_name_form =
- link name must be of the form `name = "string"`
-
-metadata_link_kind_form =
- link kind must be of the form `kind = "string"`
-
-metadata_link_modifiers_form =
- link modifiers must be of the form `modifiers = "string"`
-
-metadata_link_cfg_form =
- link cfg must be of the form `cfg(/* predicate */)`
-
-metadata_wasm_import_form =
- wasm import module must be of the form `wasm_import_module = "string"`
+metadata_dl_error =
+ {$err}
metadata_empty_link_name =
link name must not be empty
.label = empty link name
-metadata_link_framework_apple =
- link kind `framework` is only supported on Apple targets
-
-metadata_framework_only_windows =
- link kind `raw-dylib` is only supported on Windows targets
-
-metadata_unknown_link_kind =
- unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
- .label = unknown link kind
-
-metadata_multiple_link_modifiers =
- multiple `modifiers` arguments in a single `#[link]` attribute
-
-metadata_multiple_cfgs =
- multiple `cfg` arguments in a single `#[link]` attribute
-
-metadata_link_cfg_single_predicate =
- link cfg must have a single predicate argument
-
-metadata_multiple_wasm_import =
- multiple `wasm_import_module` arguments in a single `#[link]` attribute
-
-metadata_unexpected_link_arg =
- unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-
-metadata_invalid_link_modifier =
- invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-
-metadata_multiple_modifiers =
- multiple `{$modifier}` modifiers in a single `modifiers` argument
-
-metadata_bundle_needs_static =
- linking modifier `bundle` is only compatible with `static` linking kind
-
-metadata_whole_archive_needs_static =
- linking modifier `whole-archive` is only compatible with `static` linking kind
-
-metadata_as_needed_compatibility =
- linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
-
-metadata_unknown_link_modifier =
- unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
-
-metadata_incompatible_wasm_link =
- `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
-
-metadata_link_requires_name =
- `#[link]` attribute requires a `name = "string"` argument
- .label = missing `name` argument
-
-metadata_raw_dylib_no_nul =
- link name must not contain NUL characters if link kind is `raw-dylib`
-
-metadata_link_ordinal_raw_dylib =
- `#[link_ordinal]` is only supported if link kind is `raw-dylib`
-
-metadata_lib_framework_apple =
- library kind `framework` is only supported on Apple targets
-
metadata_empty_renaming_target =
an empty renaming target was specified for library `{$lib_name}`
-metadata_renaming_no_link =
- renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+metadata_extern_location_not_exist =
+ extern location for {$crate_name} does not exist: {$location}
-metadata_multiple_renamings =
- multiple renamings were specified for library `{$lib_name}`
-
-metadata_no_link_mod_override =
- overriding linking modifiers from command line is not supported
-
-metadata_unsupported_abi_i686 =
- ABI not supported by `#[link(kind = "raw-dylib")]` on i686
-
-metadata_unsupported_abi =
- ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+metadata_extern_location_not_file =
+ extern location for {$crate_name} is not a file: {$location}
metadata_fail_create_file_encoder =
failed to create file encoder: {$err}
@@ -136,72 +63,189 @@
metadata_fail_write_file =
failed to write to the file: {$err}
-metadata_crate_not_panic_runtime =
- the crate `{$crate_name}` is not a panic runtime
+metadata_failed_create_encoded_metadata =
+ failed to create encoded metadata from file: {$err}
-metadata_no_panic_strategy =
- the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+metadata_failed_create_file =
+ failed to create the file {$filename}: {$err}
-metadata_profiler_builtins_needs_core =
- `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+metadata_failed_create_tempdir =
+ couldn't create a temp dir: {$err}
-metadata_not_profiler_runtime =
- the crate `{$crate_name}` is not a profiler runtime
+metadata_failed_write_error =
+ failed to write {$filename}: {$err}
-metadata_no_multiple_global_alloc =
- cannot define multiple global allocators
- .label = cannot define a new global allocator
+metadata_found_crate_versions =
+ the following crate versions were found:{$found_crates}
-metadata_prev_global_alloc =
- previous global allocator defined here
+metadata_found_staticlib =
+ found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+ .help = please recompile that crate using --crate-type lib
+
+metadata_framework_only_windows =
+ link kind `raw-dylib` is only supported on Windows targets
+
+metadata_global_alloc_required =
+ no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_import_name_type_form =
+ import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_raw =
+ import name type can only be used with link kind `raw-dylib`
+
+metadata_import_name_type_x86 =
+ import name type is only supported on x86
+
+metadata_incompatible_panic_in_drop_strategy =
+ the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_rustc =
+ found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+ .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+
+metadata_incompatible_wasm_link =
+ `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+metadata_install_missing_components =
+ maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_invalid_link_modifier =
+ invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_invalid_meta_files =
+ found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_lib_filename_form =
+ file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
+
+metadata_lib_framework_apple =
+ library kind `framework` is only supported on Apple targets
+
+metadata_lib_required =
+ crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+
+metadata_link_cfg_form =
+ link cfg must be of the form `cfg(/* predicate */)`
+
+metadata_link_cfg_single_predicate =
+ link cfg must have a single predicate argument
+
+metadata_link_framework_apple =
+ link kind `framework` is only supported on Apple targets
+
+metadata_link_kind_form =
+ link kind must be of the form `kind = "string"`
+
+metadata_link_modifiers_form =
+ link modifiers must be of the form `modifiers = "string"`
+
+metadata_link_name_form =
+ link name must be of the form `name = "string"`
+
+metadata_link_ordinal_raw_dylib =
+ `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+
+metadata_link_requires_name =
+ `#[link]` attribute requires a `name = "string"` argument
+ .label = missing `name` argument
+
+metadata_missing_native_library =
+ could not find native static library `{$libname}`, perhaps an -L flag is missing?
+
+metadata_multiple_candidates =
+ multiple candidates for `{$flavor}` dependency `{$crate_name}` found
+
+metadata_multiple_cfgs =
+ multiple `cfg` arguments in a single `#[link]` attribute
+
+metadata_multiple_import_name_type =
+ multiple `import_name_type` arguments in a single `#[link]` attribute
+
+metadata_multiple_kinds_in_link =
+ multiple `kind` arguments in a single `#[link]` attribute
+
+metadata_multiple_link_modifiers =
+ multiple `modifiers` arguments in a single `#[link]` attribute
+
+metadata_multiple_modifiers =
+ multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+metadata_multiple_names_in_link =
+ multiple `name` arguments in a single `#[link]` attribute
+
+metadata_multiple_renamings =
+ multiple renamings were specified for library `{$lib_name}`
+
+metadata_multiple_wasm_import =
+ multiple `wasm_import_module` arguments in a single `#[link]` attribute
+
+metadata_newer_crate_version =
+ found possibly newer version of crate `{$crate_name}`{$add_info}
+ .note = perhaps that crate needs to be recompiled?
+
+metadata_no_crate_with_triple =
+ couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+
+metadata_no_dylib_plugin =
+ plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_no_link_mod_override =
+ overriding linking modifiers from command line is not supported
metadata_no_multiple_alloc_error_handler =
cannot define multiple allocation error handlers
.label = cannot define a new allocation error handler
-metadata_prev_alloc_error_handler =
- previous allocation error handler defined here
+metadata_no_multiple_global_alloc =
+ cannot define multiple global allocators
+ .label = cannot define a new global allocator
-metadata_conflicting_global_alloc =
- the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
-
-metadata_conflicting_alloc_error_handler =
- the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
-
-metadata_global_alloc_required =
- no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+metadata_no_panic_strategy =
+ the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
metadata_no_transitive_needs_dep =
the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
-metadata_failed_write_error =
- failed to write {$filename}: {$err}
-
-metadata_missing_native_library =
- could not find native static library `{$libname}`, perhaps an -L flag is missing?
-
-metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
-
-metadata_failed_create_tempdir =
- couldn't create a temp dir: {$err}
-
-metadata_failed_create_file =
- failed to create the file {$filename}: {$err}
-
-metadata_failed_create_encoded_metadata =
- failed to create encoded metadata from file: {$err}
-
metadata_non_ascii_name =
cannot load a crate with a non-ascii name `{$crate_name}`
-metadata_extern_location_not_exist =
- extern location for {$crate_name} does not exist: {$location}
+metadata_not_profiler_runtime =
+ the crate `{$crate_name}` is not a profiler runtime
-metadata_extern_location_not_file =
- extern location for {$crate_name} is not a file: {$location}
+metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
-metadata_multiple_candidates =
- multiple candidates for `{$flavor}` dependency `{$crate_name}` found
+metadata_prev_alloc_error_handler =
+ previous allocation error handler defined here
+
+metadata_prev_global_alloc =
+ previous global allocator defined here
+
+metadata_profiler_builtins_needs_core =
+ `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+metadata_raw_dylib_no_nul =
+ link name must not contain NUL characters if link kind is `raw-dylib`
+
+metadata_renaming_no_link =
+ renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+metadata_required_panic_strategy =
+ the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_rlib_required =
+ crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+
+metadata_rustc_lib_required =
+ crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+ .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
+ .help = try adding `extern crate rustc_driver;` at the top level of this crate
+
+metadata_stable_crate_id_collision =
+ found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+
+metadata_std_required =
+ `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
metadata_symbol_conflicts_current =
the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
@@ -209,80 +253,36 @@
metadata_symbol_conflicts_others =
found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
-metadata_stable_crate_id_collision =
- found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
-
-metadata_dl_error =
- {$err}
-
-metadata_newer_crate_version =
- found possibly newer version of crate `{$crate_name}`{$add_info}
- .note = perhaps that crate needs to be recompiled?
-
-metadata_found_crate_versions =
- the following crate versions were found:{$found_crates}
-
-metadata_no_crate_with_triple =
- couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
-
-metadata_found_staticlib =
- found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
- .help = please recompile that crate using --crate-type lib
-
-metadata_incompatible_rustc =
- found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
- .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
-
-metadata_invalid_meta_files =
- found invalid metadata files for crate `{$crate_name}`{$add_info}
-
-metadata_cannot_find_crate =
- can't find crate for `{$crate_name}`{$add_info}
-
-metadata_no_dylib_plugin =
- plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+metadata_target_no_std_support =
+ the `{$locator_triple}` target may not support the standard library
metadata_target_not_installed =
the `{$locator_triple}` target may not be installed
-metadata_target_no_std_support =
- the `{$locator_triple}` target may not support the standard library
+metadata_two_panic_runtimes =
+ cannot link together two panic runtimes: {$prev_name} and {$cur_name}
-metadata_consider_downloading_target =
- consider downloading the target with `rustup target add {$locator_triple}`
-
-metadata_std_required =
- `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
-
-metadata_consider_building_std =
- consider building the standard library from source with `cargo build -Zbuild-std`
-
-metadata_compiler_missing_profiler =
- the compiler may have been built without the profiler runtime
-
-metadata_install_missing_components =
- maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
-
-metadata_cant_find_crate =
- can't find crate
-
-metadata_crate_location_unknown_type =
- extern location for {$crate_name} is of an unknown type: {$path}
-
-metadata_lib_filename_form =
- file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
-
-metadata_multiple_import_name_type =
- multiple `import_name_type` arguments in a single `#[link]` attribute
-
-metadata_import_name_type_form =
- import name type must be of the form `import_name_type = "string"`
-
-metadata_import_name_type_x86 =
- import name type is only supported on x86
+metadata_unexpected_link_arg =
+ unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
metadata_unknown_import_name_type =
unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
-metadata_import_name_type_raw =
- import name type can only be used with link kind `raw-dylib`
+metadata_unknown_link_kind =
+ unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+ .label = unknown link kind
+
+metadata_unknown_link_modifier =
+ unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_unsupported_abi =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+
+metadata_unsupported_abi_i686 =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+
+metadata_wasm_import_form =
+ wasm import module must be of the form `wasm_import_module = "string"`
+
+metadata_whole_archive_needs_static =
+ linking modifier `whole-archive` is only compatible with `static` linking kind
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 209bf39..aaf72ab 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -4,7 +4,7 @@
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
-use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind};
use rustc_ast::{self as ast, *};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::svh::Svh;
@@ -373,7 +373,7 @@
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
let private_dep =
- self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep);
+ self.sess.opts.externs.get(name.as_str()).is_some_and(|e| e.is_private_dep);
// Claim this crate number and cache it
let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
@@ -1048,7 +1048,7 @@
}
}
- let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc));
+ let name = Symbol::intern(&global_fn_name(sym::alloc));
let mut f = Finder { name, spans: Vec::new() };
visit::walk_crate(&mut f, krate);
f.spans
@@ -1070,7 +1070,7 @@
}
}
- let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom));
+ let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
let mut f = Finder { name, spans: Vec::new() };
visit::walk_crate(&mut f, krate);
f.spans
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 1aab4ad..ceb348f 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -567,7 +567,7 @@
let mut err_data: Option<Vec<PathBuf>> = None;
for (lib, kind) in m {
info!("{} reading metadata from: {}", flavor, lib.display());
- if flavor == CrateFlavor::Rmeta && lib.metadata().map_or(false, |m| m.len() == 0) {
+ if flavor == CrateFlavor::Rmeta && lib.metadata().is_ok_and(|m| m.len() == 0) {
// Empty files will cause get_metadata_section to fail. Rmeta
// files can be empty, for example with binaries (which can
// often appear with `cargo check` when checking a library as
@@ -602,7 +602,7 @@
}
};
// If we see multiple hashes, emit an error about duplicate candidates.
- if slot.as_ref().map_or(false, |s| s.0 != hash) {
+ if slot.as_ref().is_some_and(|s| s.0 != hash) {
if let Some(candidates) = err_data {
return Err(CrateError::MultipleCandidates(
self.crate_name,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 834e245..cc4e60c 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1060,7 +1060,7 @@
.expect("argument names not encoded for a function")
.decode((self, sess))
.nth(0)
- .map_or(false, |ident| ident.name == kw::SelfLower)
+ .is_some_and(|ident| ident.name == kw::SelfLower)
}
fn get_associated_item_or_field_def_ids(
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 64d511c..3d581da 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -1,45 +1,45 @@
-middle_drop_check_overflow =
- overflow while adding drop-check rules for {$ty}
- .note = overflowed on {$overflow_ty}
-
-middle_opaque_hidden_type_mismatch =
- concrete type differs from previous defining opaque type use
- .label = expected `{$self_ty}`, got `{$other_ty}`
+middle_cannot_be_normalized =
+ unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
middle_conflict_types =
this expression supplies two conflicting concrete types for the same opaque type
-middle_previous_use_here =
- previous use here
+middle_const_eval_non_int =
+ constant evaluation of enum discriminant resulted in non-integer
+
+middle_const_not_used_in_type_alias =
+ const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+
+middle_cycle =
+ a cycle occurred during layout computation
+
+middle_drop_check_overflow =
+ overflow while adding drop-check rules for {$ty}
+ .note = overflowed on {$overflow_ty}
middle_limit_invalid =
`limit` must be a non-negative integer
.label = {$error_str}
+middle_opaque_hidden_type_mismatch =
+ concrete type differs from previous defining opaque type use
+ .label = expected `{$self_ty}`, got `{$other_ty}`
+
+middle_previous_use_here =
+ previous use here
+
middle_recursion_limit_reached =
reached the recursion limit finding the struct tail for `{$ty}`
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]`
-middle_const_eval_non_int =
- constant evaluation of enum discriminant resulted in non-integer
+middle_requires_lang_item = requires `{$name}` lang_item
+
+middle_strict_coherence_needs_negative_coherence =
+ to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
+ .label = due to this attribute
middle_unknown_layout =
the type `{$ty}` has an unknown layout
middle_values_too_big =
values of the type `{$ty}` are too big for the current architecture
-
-middle_cannot_be_normalized =
- unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
-
-middle_cycle =
- a cycle occurred during layout computation
-
-middle_strict_coherence_needs_negative_coherence =
- to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
- .label = due to this attribute
-
-middle_requires_lang_item = requires `{$name}` lang_item
-
-middle_const_not_used_in_type_alias =
- const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 6a1a2a0..a149a61 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -121,6 +121,7 @@
>,
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
+ [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
[] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
[] mod_child: rustc_middle::metadata::ModChild,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 3b59df7..d1ddc8f 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -410,7 +410,7 @@
/// item (possibly associated), a closure, or a `hir::AnonConst`.
pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
let parent = self.parent_id(hir_id);
- assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
+ assert!(self.find(parent).is_some_and(|n| is_body_owner(n, hir_id)), "{hir_id:?}");
parent
}
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index ac0b284..45a07fd 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -115,7 +115,7 @@
/// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
pub fn is_foreign_item(self, def_id: impl Into<DefId>) -> bool {
self.opt_parent(def_id.into())
- .map_or(false, |parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
+ .is_some_and(|parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
}
}
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index c266584..14343ac 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -468,8 +468,7 @@
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let expn_data = span.ctxt().outer_expn_data();
match expn_data.kind {
- ExpnKind::Inlined
- | ExpnKind::Root
+ ExpnKind::Root
| ExpnKind::Desugaring(
DesugaringKind::ForLoop | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy,
) => false,
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index aeb6a16..f45cf78 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -94,8 +94,7 @@
impl EffectiveVisibilities {
pub fn is_public_at_level(&self, id: LocalDefId, level: Level) -> bool {
- self.effective_vis(id)
- .map_or(false, |effective_vis| effective_vis.is_public_at_level(level))
+ self.effective_vis(id).is_some_and(|effective_vis| effective_vis.is_public_at_level(level))
}
/// See `Level::Reachable`.
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 89fc864..6354c0a 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -375,7 +375,7 @@
let parent_def_id = self.hir().get_parent_item(id);
let skip = self
.lookup_deprecation_entry(parent_def_id.to_def_id())
- .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
+ .is_some_and(|parent_depr| parent_depr.same_origin(&depr_entry));
// #[deprecated] doesn't emit a notice if we're not on the
// topmost deprecation. For example, if a struct is deprecated,
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 1319ddb..9d70dbf 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -27,6 +27,7 @@
switch_sources: OnceCell<SwitchSources>,
is_cyclic: OnceCell<bool>,
postorder: OnceCell<Vec<BasicBlock>>,
+ dominators: OnceCell<Dominators<BasicBlock>>,
}
impl<'tcx> BasicBlocks<'tcx> {
@@ -41,8 +42,8 @@
*self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
}
- pub fn dominators(&self) -> Dominators<BasicBlock> {
- dominators(&self)
+ pub fn dominators(&self) -> &Dominators<BasicBlock> {
+ self.cache.dominators.get_or_init(|| dominators(self))
}
/// Returns predecessors for each basic block.
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ff54ec5..f31b343 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -334,10 +334,7 @@
}
pub fn modify_size_estimate(&mut self, delta: usize) {
- assert!(self.size_estimate.is_some());
- if let Some(size_estimate) = self.size_estimate {
- self.size_estimate = Some(size_estimate + delta);
- }
+ *self.size_estimate.as_mut().unwrap() += delta;
}
pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 21faf19..6d6d71b 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -603,7 +603,11 @@
/// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
/// > the place or one of its "parents" occurred more recently than a move out of it. This does not
/// > consider indirect assignments.
- Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction },
+ ///
+ /// The `replace` flag indicates whether this terminator was created as part of an assignment.
+ /// This should only be used for diagnostic purposes, and does not have any operational
+ /// meaning.
+ Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
/// the referred to function. The operand types must match the argument types of the function.
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 596dd80..942654b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -504,6 +504,7 @@
place,
target: _,
unwind: _,
+ replace: _,
} => {
self.visit_place(
place,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 5b0b40c..0a903a7 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -1108,3 +1108,14 @@
Unimplemented,
FulfillmentError,
}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum DefiningAnchor {
+ /// `DefId` of the item.
+ Bind(LocalDefId),
+ /// When opaque types are not resolved, we `Bubble` up, meaning
+ /// return the opaque/hidden type pair from query, for caller of query to handle it.
+ Bubble,
+ /// Used to catch type mismatch errors when handling opaque types.
+ Error,
+}
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index c4f8718..eae5a28 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -95,8 +95,6 @@
#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
pub struct NoSolution;
-pub type Fallible<T> = Result<T, NoSolution>;
-
impl<'tcx> From<TypeError<'tcx>> for NoSolution {
fn from(_: TypeError<'tcx>) -> NoSolution {
NoSolution
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 1511c90..2c5b64a 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -5,13 +5,13 @@
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
use crate::traits::query::NoSolution;
-use crate::traits::Canonical;
+use crate::traits::{Canonical, DefiningAnchor};
use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
TypeVisitor,
};
-pub type EvaluationCache<'tcx> = Cache<CanonicalGoal<'tcx>, QueryResult<'tcx>>;
+pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>;
/// A goal is a statement, i.e. `predicate`, we want to prove
/// given some assumptions, i.e. `param_env`.
@@ -96,7 +96,31 @@
Overflow,
}
-pub type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub struct QueryInput<'tcx, T> {
+ pub goal: Goal<'tcx, T>,
+ pub anchor: DefiningAnchor,
+ pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+pub struct PredefinedOpaquesData<'tcx> {
+ pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
+}
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<'tcx>>);
+
+impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
+ type Target = PredefinedOpaquesData<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+pub type CanonicalInput<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, QueryInput<'tcx, T>>;
pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
@@ -165,3 +189,40 @@
ControlFlow::Continue(())
}
}
+
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(FallibleTypeFolder::interner(folder).mk_predefined_opaques_in_body(
+ PredefinedOpaquesData {
+ opaque_types: self
+ .opaque_types
+ .iter()
+ .map(|opaque| opaque.try_fold_with(folder))
+ .collect::<Result<_, F::Error>>()?,
+ },
+ ))
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ TypeFolder::interner(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData {
+ opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
+ })
+ }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> std::ops::ControlFlow<V::BreakTy> {
+ self.opaque_types.visit_with(visitor)
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 5393dba..2bde55b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -21,7 +21,9 @@
use crate::thir::Thir;
use crate::traits;
use crate::traits::solve;
-use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
+use crate::traits::solve::{
+ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
+};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
@@ -140,6 +142,7 @@
layout: InternedSet<'tcx, LayoutS>,
adt_def: InternedSet<'tcx, AdtDefData>,
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
+ predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
fields: InternedSet<'tcx, List<FieldIdx>>,
}
@@ -164,6 +167,7 @@
layout: Default::default(),
adt_def: Default::default(),
external_constraints: Default::default(),
+ predefined_opaques_in_body: Default::default(),
fields: Default::default(),
}
}
@@ -1520,6 +1524,8 @@
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
ExternalConstraints -> ExternalConstraints<'tcx>,
+ predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
+ PredefinedOpaques -> PredefinedOpaques<'tcx>,
}
macro_rules! slice_interners {
@@ -2341,7 +2347,7 @@
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
+ self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
}
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
@@ -2474,7 +2480,7 @@
|tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
providers.has_panic_handler = |tcx, LocalCrate| {
// We want to check if the panic handler was defined in this crate
- tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
+ tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
};
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
}
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index 5c1c419..9de77b9 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -78,7 +78,7 @@
{
TLV.with(|tlv| {
let old = tlv.replace(erase(context));
- let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
+ let _reset = rustc_data_structures::defer(move || tlv.set(old));
f()
})
}
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 99174ba..b0ffe78 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -298,7 +298,7 @@
.iter()
.rev()
.take_while(|param| {
- param.default_value(tcx).map_or(false, |default| {
+ param.default_value(tcx).is_some_and(|default| {
default.subst(tcx, substs) == substs[param.index as usize]
})
})
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 8c69894..e641d1e 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -659,7 +659,7 @@
} else {
None
};
- let has_upvars = upvars_ty.map_or(false, |ty| !ty.tuple_fields().is_empty());
+ let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty());
debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
struct PolymorphizationFolder<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c9cd644..a8d0dca 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -996,17 +996,11 @@
}
}
- /// This function returns the inner `AliasTy` if this term is a projection.
- ///
- /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
- /// deal with constants.
- pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+ /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`.
+ pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
match self.unpack() {
- TermKind::Ty(ty) => match ty.kind() {
- ty::Alias(kind, alias_ty) => match kind {
- AliasKind::Projection | AliasKind::Inherent => Some(*alias_ty),
- AliasKind::Opaque => None,
- },
+ TermKind::Ty(ty) => match *ty.kind() {
+ ty::Alias(_kind, alias_ty) => Some(alias_ty),
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
@@ -2220,8 +2214,8 @@
let impl_trait_ref2 = self.impl_trait_ref(def_id2);
// If either trait impl references an error, they're allowed to overlap,
// as one of them essentially doesn't exist.
- if impl_trait_ref1.map_or(false, |tr| tr.subst_identity().references_error())
- || impl_trait_ref2.map_or(false, |tr| tr.subst_identity().references_error())
+ if impl_trait_ref1.is_some_and(|tr| tr.subst_identity().references_error())
+ || impl_trait_ref2.is_some_and(|tr| tr.subst_identity().references_error())
{
return Some(ImplOverlapKind::Permitted { marker: false });
}
@@ -2242,7 +2236,7 @@
let is_marker_overlap = {
let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
- trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker)
+ trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
};
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
};
@@ -2494,9 +2488,7 @@
&& if self.features().collapse_debuginfo {
span.in_macro_expansion_with_collapse_debuginfo()
} else {
- // Inlined spans should not be collapsed as that leads to all of the
- // inlined code being attributed to the inline callsite.
- span.from_expansion() && !span.is_inlined()
+ span.from_expansion()
}
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a064174..d6c88ea 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -700,7 +700,7 @@
if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
}
}
- ty::Error(_) => p!("[type error]"),
+ ty::Error(_) => p!("{{type error}}"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
ty::BoundTyKind::Anon => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
@@ -1379,8 +1379,8 @@
},
// FIXME(generic_const_exprs):
// write out some legible representation of an abstract const?
- ty::ConstKind::Expr(_) => p!("[const expr]"),
- ty::ConstKind::Error(_) => p!("[const error]"),
+ ty::ConstKind::Expr(_) => p!("{{const expr}}"),
+ ty::ConstKind::Error(_) => p!("{{const error}}"),
};
Ok(self)
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index eb903eb..ba05135 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -518,6 +518,42 @@
Ok(())
}
+ /// Checks whether each generic argument is simply a unique generic placeholder.
+ ///
+ /// This is used in the new solver, which canonicalizes params to placeholders
+ /// for better caching.
+ pub fn uses_unique_placeholders_ignoring_regions(
+ self,
+ substs: SubstsRef<'tcx>,
+ ) -> Result<(), NotUniqueParam<'tcx>> {
+ let mut seen = GrowableBitSet::default();
+ for arg in substs {
+ match arg.unpack() {
+ // Ignore regions, since we can't resolve those in a canonicalized
+ // query in the trait solver.
+ GenericArgKind::Lifetime(_) => {}
+ GenericArgKind::Type(t) => match t.kind() {
+ ty::Placeholder(p) => {
+ if !seen.insert(p.bound.var) {
+ return Err(NotUniqueParam::DuplicateParam(t.into()));
+ }
+ }
+ _ => return Err(NotUniqueParam::NotParam(t.into())),
+ },
+ GenericArgKind::Const(c) => match c.kind() {
+ ty::ConstKind::Placeholder(p) => {
+ if !seen.insert(p.bound) {
+ return Err(NotUniqueParam::DuplicateParam(c.into()));
+ }
+ }
+ _ => return Err(NotUniqueParam::NotParam(c.into())),
+ },
+ }
+ }
+
+ Ok(())
+ }
+
/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
/// that closures have a `DefId`, but the closure *expression* also
/// has a `HirId` that is located within the context where the
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index f346cd4..cb265cf 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -1,62 +1,40 @@
-mir_build_unconditional_recursion = function cannot return without recursing
- .label = cannot return without recursing
- .help = a `loop` may express intention better if this is on purpose
+mir_build_adt_defined_here = `{$ty}` defined here
-mir_build_unconditional_recursion_call_site_label = recursive call site
+mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
- call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
- .note = consult the function's documentation for information on how to avoid undefined behavior
- .label = call to unsafe function
+mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
- call to unsafe function is unsafe and requires unsafe block (error E0133)
- .note = consult the function's documentation for information on how to avoid undefined behavior
- .label = call to unsafe function
+mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
-mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
- use of inline assembly is unsafe and requires unsafe block (error E0133)
- .note = inline assembly is entirely unchecked and can cause undefined behavior
- .label = use of inline assembly
+mir_build_bindings_with_variant_name =
+ pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
+ .suggestion = to match on the variant, qualify the path
-mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
- initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
- block (error E0133)
- .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
- .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_borrow = value is borrowed by `{$name}` here
-mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
- use of mutable static is unsafe and requires unsafe block (error E0133)
- .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
- .label = use of mutable static
-
-mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
- use of extern static is unsafe and requires unsafe block (error E0133)
- .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
- .label = use of extern static
-
-mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
- dereference of raw pointer is unsafe and requires unsafe block (error E0133)
- .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
- .label = dereference of raw pointer
-
-mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
- access to union field is unsafe and requires unsafe block (error E0133)
- .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
- .label = access to union field
-
-mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
- mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
- .note = mutating layout constrained fields cannot statically be checked for valid values
- .label = mutation of layout constrained field
-
-mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
- borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_layout_constrained_field_requires_unsafe =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
.note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
.label = borrow of layout constrained field with interior mutability
-mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
- call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+ .label = borrow of layout constrained field with interior mutability
+
+mir_build_borrow_of_moved_value = borrow of moved value
+ .label = value moved into `{$name}` here
+ .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
+ .value_borrowed_label = value borrowed here after move
+ .suggestion = borrow this binding in the pattern to avoid moving the value
+
+mir_build_call_to_fn_with_requires_unsafe =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
+ .note = can only be called if the required target features are available
+ .label = call to function with `#[target_feature]`
+
+mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
.note = can only be called if the required target features are available
.label = call to function with `#[target_feature]`
@@ -70,55 +48,24 @@
.note = consult the function's documentation for information on how to avoid undefined behavior
.label = call to unsafe function
-mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- call to unsafe function `{$function}` is unsafe and requires unsafe function or block
- .note = consult the function's documentation for information on how to avoid undefined behavior
- .label = call to unsafe function
-
mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed =
call to unsafe function is unsafe and requires unsafe function or block
.note = consult the function's documentation for information on how to avoid undefined behavior
.label = call to unsafe function
-mir_build_inline_assembly_requires_unsafe =
- use of inline assembly is unsafe and requires unsafe block
- .note = inline assembly is entirely unchecked and can cause undefined behavior
- .label = use of inline assembly
+mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ call to unsafe function `{$function}` is unsafe and requires unsafe function or block
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
-mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- use of inline assembly is unsafe and requires unsafe function or block
- .note = inline assembly is entirely unchecked and can cause undefined behavior
- .label = use of inline assembly
+mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
-mir_build_initializing_type_with_requires_unsafe =
- initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
- .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
- .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
-mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
- .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
- .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_const_pattern_depends_on_generic_parameter =
+ constant pattern depends on a generic parameter
-mir_build_mutable_static_requires_unsafe =
- use of mutable static is unsafe and requires unsafe block
- .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
- .label = use of mutable static
-
-mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- use of mutable static is unsafe and requires unsafe function or block
- .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
- .label = use of mutable static
-
-mir_build_extern_static_requires_unsafe =
- use of extern static is unsafe and requires unsafe block
- .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
- .label = use of extern static
-
-mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- use of extern static is unsafe and requires unsafe function or block
- .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
- .label = use of extern static
+mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
mir_build_deref_raw_pointer_requires_unsafe =
dereference of raw pointer is unsafe and requires unsafe block
@@ -130,117 +77,46 @@
.note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
.label = dereference of raw pointer
-mir_build_union_field_requires_unsafe =
- access to union field is unsafe and requires unsafe block
- .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
- .label = access to union field
+mir_build_extern_static_requires_unsafe =
+ use of extern static is unsafe and requires unsafe block
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
-mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- access to union field is unsafe and requires unsafe function or block
- .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
- .label = access to union field
+mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of extern static is unsafe and requires unsafe function or block
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
-mir_build_mutation_of_layout_constrained_field_requires_unsafe =
- mutation of layout constrained field is unsafe and requires unsafe block
- .note = mutating layout constrained fields cannot statically be checked for valid values
- .label = mutation of layout constrained field
+mir_build_float_pattern = floating-point types cannot be used in patterns
-mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- mutation of layout constrained field is unsafe and requires unsafe function or block
- .note = mutating layout constrained fields cannot statically be checked for valid values
- .label = mutation of layout constrained field
+mir_build_indirect_structural_match =
+ to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
-mir_build_borrow_of_layout_constrained_field_requires_unsafe =
- borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
- .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
- .label = borrow of layout constrained field with interior mutability
+mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
-mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
- .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
- .label = borrow of layout constrained field with interior mutability
+mir_build_initializing_type_with_requires_unsafe =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
-mir_build_call_to_fn_with_requires_unsafe =
- call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
- .note = can only be called if the required target features are available
- .label = call to function with `#[target_feature]`
+mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
-mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
- call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
- .note = can only be called if the required target features are available
- .label = call to function with `#[target_feature]`
+mir_build_inline_assembly_requires_unsafe =
+ use of inline assembly is unsafe and requires unsafe block
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
-mir_build_unused_unsafe = unnecessary `unsafe` block
- .label = unnecessary `unsafe` block
+mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of inline assembly is unsafe and requires unsafe function or block
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
-mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
-mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+mir_build_interpreted_as_const = introduce a variable instead
-mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
- .def_note = `{$peeled_ty}` defined here
- .type_note = the matched value is of type `{$ty}`
- .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
- .reference_note = references are always considered inhabited
- .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
-
-mir_build_static_in_pattern = statics cannot be referenced in patterns
-
-mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
-
-mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
-
-mir_build_non_const_path = runtime values cannot be referenced in patterns
-
-mir_build_unreachable_pattern = unreachable pattern
- .label = unreachable pattern
- .catchall_label = matches any value
-
-mir_build_const_pattern_depends_on_generic_parameter =
- constant pattern depends on a generic parameter
-
-mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
-
-mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
- lower range bound must be less than or equal to upper
- .label = lower bound larger than upper bound
- .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
-
-mir_build_literal_in_range_out_of_bounds =
- literal out of range for `{$ty}`
- .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
-
-mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
-
-mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
- [one] pattern
- *[other] patterns
- } in let chain
- .note = {$count ->
- [one] this pattern
- *[other] these patterns
- } will always match
- .help = consider moving {$count ->
- [one] it
- *[other] them
- } outside of the construct
-
-mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
- [one] pattern
- *[other] patterns
- } in let chain
- .note = {$count ->
- [one] this pattern
- *[other] these patterns
- } will always match
- .help = consider moving {$count ->
- [one] it
- *[other] them
- } into the body
-
-mir_build_bindings_with_variant_name =
- pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
- .suggestion = to match on the variant, qualify the path
+mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
[one] pattern
@@ -282,78 +158,97 @@
} will always match, so the loop will never exit
.help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it
-mir_build_borrow_of_moved_value = borrow of moved value
- .label = value moved into `{$name}` here
- .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
- .value_borrowed_label = value borrowed here after move
- .suggestion = borrow this binding in the pattern to avoid moving the value
+mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
+ [one] pattern
+ *[other] patterns
+ } in let chain
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match
+ .help = consider moving {$count ->
+ [one] it
+ *[other] them
+ } outside of the construct
-mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
+mir_build_literal_in_range_out_of_bounds =
+ literal out of range for `{$ty}`
+ .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
-mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
+mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
+ lower range bound must be less than or equal to upper
+ .label = lower bound larger than upper bound
+ .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
-mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
+mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
-mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
-
-mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
-
-mir_build_borrow = value is borrowed by `{$name}` here
+mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
mir_build_moved = value is moved into `{$name}` here
-mir_build_union_pattern = cannot use unions in constant patterns
+mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
-mir_build_type_not_structural =
- to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
-mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
-mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
+mir_build_mutable_static_requires_unsafe =
+ use of mutable static is unsafe and requires unsafe block
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
-mir_build_float_pattern = floating-point types cannot be used in patterns
+mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of mutable static is unsafe and requires unsafe function or block
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
-mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+mir_build_mutation_of_layout_constrained_field_requires_unsafe =
+ mutation of layout constrained field is unsafe and requires unsafe block
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
-mir_build_indirect_structural_match =
- to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ mutation of layout constrained field is unsafe and requires unsafe function or block
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
-mir_build_nontrivial_structural_match =
- to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
-
-mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
-
-mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
-
-mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
- .range = ... with this range
- .note = you likely meant to write mutually exclusive ranges
+mir_build_non_const_path = runtime values cannot be referenced in patterns
mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
.help = ensure that all variants are matched explicitly by adding the suggested match arms
.note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
-mir_build_uncovered = {$count ->
- [1] pattern `{$witness_1}`
- [2] patterns `{$witness_1}` and `{$witness_2}`
- [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
- *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
- } not covered
+mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
+ .def_note = `{$peeled_ty}` defined here
+ .type_note = the matched value is of type `{$ty}`
+ .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
+ .reference_note = references are always considered inhabited
+ .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+mir_build_nontrivial_structural_match =
+ to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+
+mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
+ .range = ... with this range
+ .note = you likely meant to write mutually exclusive ranges
mir_build_pattern_not_covered = refutable pattern in {$origin}
.pattern_ty = the matched value is of type `{$pattern_ty}`
-mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
-mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
-mir_build_adt_defined_here = `{$ty}` defined here
+mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
+ .attributes = no other attributes may be applied
+ .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
+ .missing_box = `#[rustc_box]` requires the `owned_box` lang item
-mir_build_variant_defined_here = not covered
+mir_build_static_in_pattern = statics cannot be referenced in patterns
-mir_build_interpreted_as_const = introduce a variable instead
+mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
-mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
[one] variant that isn't
@@ -365,10 +260,117 @@
*[other] variants that aren't
} matched
-mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
+ [one] pattern
+ *[other] patterns
+ } in let chain
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match
+ .help = consider moving {$count ->
+ [one] it
+ *[other] them
+ } into the body
+mir_build_type_not_structural =
+ to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
-mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
- .attributes = no other attributes may be applied
- .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
- .missing_box = `#[rustc_box]` requires the `owned_box` lang item
+mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
+
+mir_build_unconditional_recursion = function cannot return without recursing
+ .label = cannot return without recursing
+ .help = a `loop` may express intention better if this is on purpose
+
+mir_build_unconditional_recursion_call_site_label = recursive call site
+
+mir_build_uncovered = {$count ->
+ [1] pattern `{$witness_1}`
+ [2] patterns `{$witness_1}` and `{$witness_2}`
+ [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
+ *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
+ } not covered
+
+mir_build_union_field_requires_unsafe =
+ access to union field is unsafe and requires unsafe block
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ access to union field is unsafe and requires unsafe function or block
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_union_pattern = cannot use unions in constant patterns
+
+mir_build_unreachable_pattern = unreachable pattern
+ .label = unreachable pattern
+ .catchall_label = matches any value
+
+mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+ .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+ .label = borrow of layout constrained field with interior mutability
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+ .note = can only be called if the required target features are available
+ .label = call to function with `#[target_feature]`
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
+ call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
+ call to unsafe function is unsafe and requires unsafe block (error E0133)
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
+ dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+ .label = dereference of raw pointer
+
+mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
+ use of extern static is unsafe and requires unsafe block (error E0133)
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
+
+mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
+ block (error E0133)
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
+ use of inline assembly is unsafe and requires unsafe block (error E0133)
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
+
+mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
+ use of mutable static is unsafe and requires unsafe block (error E0133)
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
+
+mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
+ mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
+
+mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
+ access to union field is unsafe and requires unsafe block (error E0133)
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+
+mir_build_unused_unsafe = unnecessary `unsafe` block
+ .label = unnecessary `unsafe` block
+
+mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
+mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+
+mir_build_variant_defined_here = not covered
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 609ab19..ab4cd24 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -351,7 +351,7 @@
}
let popped = this.block_context.pop();
- assert!(popped.map_or(false, |bf| bf.is_statement()));
+ assert!(popped.is_some_and(|bf| bf.is_statement()));
}
// Then, the block may have an optional trailing expression which is a “return” value
@@ -367,7 +367,7 @@
unpack!(block = this.expr_into_dest(destination, block, expr));
let popped = this.block_context.pop();
- assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
+ assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
} else {
// If a block has no trailing expression, then it is given an implicit return type.
// This return type is usually `()`, unless the block is diverging, in which case the
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index b744227..ebf830c 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -57,6 +57,7 @@
place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?,
unwind: UnwindAction::Continue,
+ replace: false,
})
},
@call("mir_call", args) => {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 6941da3..744111e 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -118,7 +118,10 @@
let category = Category::of(&expr.kind).unwrap();
debug!(?category, ?expr.kind);
match category {
- Category::Constant if let NeedsTemporary::No = needs_temporary || !expr.ty.needs_drop(this.tcx, this.param_env) => {
+ Category::Constant
+ if matches!(needs_temporary, NeedsTemporary::No)
+ || !expr.ty.needs_drop(this.tcx, this.param_env) =>
+ {
let constant = this.as_constant(expr);
block.and(Operand::Constant(Box::new(constant)))
}
@@ -126,7 +129,8 @@
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
// Overwrite temp local info if we have something more interesting to record.
if !matches!(local_info, LocalInfo::Boring) {
- let decl_info = this.local_decls[operand].local_info.as_mut().assert_crate_local();
+ let decl_info =
+ this.local_decls[operand].local_info.as_mut().assert_crate_local();
if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info {
**decl_info = local_info;
}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index bcab4c0..3742d64 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -725,6 +725,7 @@
place: to_drop,
target: success,
unwind: UnwindAction::Continue,
+ replace: false,
},
);
this.diverge_from(block);
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index b01b6fb..7c0fbc6 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -91,7 +91,7 @@
use rustc_middle::mir::*;
use rustc_middle::thir::{Expr, LintLevel};
-use rustc_span::{DesugaringKind, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
#[derive(Debug)]
pub struct Scopes<'tcx> {
@@ -325,10 +325,10 @@
entry_points.sort();
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
- if entry_points.last().map_or(false, |entry_point| entry_point.0 == drop_idx) {
+ if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
needs_block[drop_idx] = Block::Own;
- while entry_points.last().map_or(false, |entry_point| entry_point.0 == drop_idx) {
+ while entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
let entry_block = entry_points.pop().unwrap().1;
T::add_entry(cfg, entry_block, block);
}
@@ -371,6 +371,7 @@
// The caller will handle this if needed.
unwind: UnwindAction::Terminate,
place: drop_data.0.local.into(),
+ replace: false,
};
cfg.terminate(block, drop_data.0.source_info, terminator);
}
@@ -731,7 +732,7 @@
fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
// If we are emitting a `drop` statement, we need to have the cached
// diverge cleanup pads ready in case that drop panics.
- let needs_cleanup = self.scopes.scopes.last().map_or(false, |scope| scope.needs_cleanup());
+ let needs_cleanup = self.scopes.scopes.last().is_some_and(|scope| scope.needs_cleanup());
let is_generator = self.generator_kind.is_some();
let unwind_to = if needs_cleanup { self.diverge_cleanup() } else { DropIdx::MAX };
@@ -1128,9 +1129,6 @@
place: Place<'tcx>,
value: Rvalue<'tcx>,
) -> BlockAnd<()> {
- let span = self.tcx.with_stable_hashing_context(|hcx| {
- span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
- });
let source_info = self.source_info(span);
// create the new block for the assignment
@@ -1148,6 +1146,7 @@
place,
target: assign,
unwind: UnwindAction::Cleanup(assign_unwind),
+ replace: true,
},
);
self.diverge_from(block);
@@ -1261,6 +1260,7 @@
place: local.into(),
target: next,
unwind: UnwindAction::Continue,
+ replace: false,
},
);
block = next;
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index dcdeaf0..7c0df20 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -781,6 +781,8 @@
pub interpreted_as_const: Option<InterpretedAsConst>,
#[subdiagnostic]
pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
+ #[note(mir_build_privately_uninhabited)]
+ pub witness_1_is_privately_uninhabited: Option<()>,
#[note(mir_build_pattern_ty)]
pub _p: (),
pub pattern_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index c864822..b20495d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -333,7 +333,7 @@
} else if let Some(box_item) = tcx.lang_items().owned_box() {
if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
- && path.res.opt_def_id().map_or(false, |did| did == box_item)
+ && path.res.opt_def_id().is_some_and(|did| did == box_item)
&& fn_path.ident.name == sym::new
&& let [value] = args
{
@@ -956,7 +956,7 @@
let is_upvar = self
.tcx
.upvars_mentioned(self.body_owner)
- .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
+ .is_some_and(|upvars| upvars.contains_key(&var_hir_id));
debug!(
"convert_var({:?}): is_upvar={}, body_owner={:?}",
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ca25f83..1e51cb9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -90,35 +90,34 @@
#[instrument(level = "trace", skip(self))]
fn visit_arm(&mut self, arm: &Arm<'tcx>) {
- match arm.guard {
- Some(Guard::If(expr)) => {
- self.with_let_source(LetSource::IfLetGuard, |this| {
- this.visit_expr(&this.thir[expr])
- });
+ self.with_lint_level(arm.lint_level, |this| {
+ match arm.guard {
+ Some(Guard::If(expr)) => {
+ this.with_let_source(LetSource::IfLetGuard, |this| {
+ this.visit_expr(&this.thir[expr])
+ });
+ }
+ Some(Guard::IfLet(ref pat, expr)) => {
+ this.with_let_source(LetSource::IfLetGuard, |this| {
+ this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
+ this.visit_pat(pat);
+ this.visit_expr(&this.thir[expr]);
+ });
+ }
+ None => {}
}
- Some(Guard::IfLet(ref pat, expr)) => {
- self.with_let_source(LetSource::IfLetGuard, |this| {
- this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
- this.visit_pat(pat);
- this.visit_expr(&this.thir[expr]);
- });
- }
- None => {}
- }
- self.visit_pat(&arm.pattern);
- self.visit_expr(&self.thir[arm.body]);
+ this.visit_pat(&arm.pattern);
+ this.visit_expr(&self.thir[arm.body]);
+ });
}
#[instrument(level = "trace", skip(self))]
fn visit_expr(&mut self, ex: &Expr<'tcx>) {
match ex.kind {
ExprKind::Scope { value, lint_level, .. } => {
- let old_lint_level = self.lint_level;
- if let LintLevel::Explicit(hir_id) = lint_level {
- self.lint_level = hir_id;
- }
- self.visit_expr(&self.thir[value]);
- self.lint_level = old_lint_level;
+ self.with_lint_level(lint_level, |this| {
+ this.visit_expr(&this.thir[value]);
+ });
return;
}
ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
@@ -190,6 +189,17 @@
self.let_source = old_let_source;
}
+ fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) {
+ if let LintLevel::Explicit(hir_id) = new_lint_level {
+ let old_lint_level = self.lint_level;
+ self.lint_level = hir_id;
+ f(self);
+ self.lint_level = old_lint_level;
+ } else {
+ f(self);
+ }
+ }
+
fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
check_for_bindings_named_same_as_variants(self, pat, rf);
@@ -236,7 +246,9 @@
for &arm in arms {
// Check the arm for some things unrelated to exhaustiveness.
let arm = &self.thir.arms[arm];
- self.check_patterns(&arm.pattern, Refutable);
+ self.with_lint_level(arm.lint_level, |this| {
+ this.check_patterns(&arm.pattern, Refutable);
+ });
}
let tarms: Vec<_> = arms
@@ -479,12 +491,30 @@
AdtDefinedHere { adt_def_span, ty, variants }
};
+ // Emit an extra note if the first uncovered witness would be uninhabited
+ // if we disregard visibility.
+ let witness_1_is_privately_uninhabited =
+ if cx.tcx.features().exhaustive_patterns
+ && let Some(witness_1) = witnesses.get(0)
+ && let ty::Adt(adt, substs) = witness_1.ty().kind()
+ && adt.is_enum()
+ && let Constructor::Variant(variant_index) = witness_1.ctor()
+ {
+ let variant = adt.variant(*variant_index);
+ let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs);
+ assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
+ !inhabited.apply_ignore_module(cx.tcx, cx.param_env)
+ } else {
+ false
+ };
+
self.error = Err(self.tcx.sess.emit_err(PatternNotCovered {
span: pat.span,
origin,
uncovered: Uncovered::new(pat.span, &cx, witnesses),
inform,
interpreted_as_const,
+ witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()),
_p: (),
pattern_ty,
let_suggestion,
diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl
index 9885415..5698367 100644
--- a/compiler/rustc_mir_dataflow/messages.ftl
+++ b/compiler/rustc_mir_dataflow/messages.ftl
@@ -1,11 +1,23 @@
+mir_dataflow_duplicate_values_for =
+ duplicate values for `{$name}`
+
mir_dataflow_path_must_end_in_filename =
path must end in a filename
-mir_dataflow_unknown_formatter =
- unknown formatter
+mir_dataflow_peek_argument_not_a_local =
+ rustc_peek: argument was not a local
-mir_dataflow_duplicate_values_for =
- duplicate values for `{$name}`
+mir_dataflow_peek_argument_untracked =
+ rustc_peek: argument untracked
+
+mir_dataflow_peek_bit_not_set =
+ rustc_peek: bit not set
+
+mir_dataflow_peek_must_be_not_temporary =
+ dataflow::sanity_check cannot feed a non-temp to rustc_peek
+
+mir_dataflow_peek_must_be_place_or_ref_place =
+ rustc_peek: argument expression must be either `place` or `&place`
mir_dataflow_requires_an_argument =
`{$name}` requires an argument
@@ -13,17 +25,5 @@
mir_dataflow_stop_after_dataflow_ended_compilation =
stop_after_dataflow ended compilation
-mir_dataflow_peek_must_be_place_or_ref_place =
- rustc_peek: argument expression must be either `place` or `&place`
-
-mir_dataflow_peek_must_be_not_temporary =
- dataflow::sanity_check cannot feed a non-temp to rustc_peek
-
-mir_dataflow_peek_bit_not_set =
- rustc_peek: bit not set
-
-mir_dataflow_peek_argument_not_a_local =
- rustc_peek: argument was not a local
-
-mir_dataflow_peek_argument_untracked =
- rustc_peek: argument untracked
+mir_dataflow_unknown_formatter =
+ unknown formatter
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 1889507..d615c83 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -237,6 +237,7 @@
place: self.place,
target: self.succ,
unwind: self.unwind.into_action(),
+ replace: false,
},
);
}
@@ -719,6 +720,7 @@
place: tcx.mk_place_deref(ptr),
target: loop_block,
unwind: unwind.into_action(),
+ replace: false,
},
);
@@ -963,8 +965,12 @@
}
fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
- let block =
- TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() };
+ let block = TerminatorKind::Drop {
+ place: self.place,
+ target,
+ unwind: unwind.into_action(),
+ replace: false,
+ };
self.new_block(unwind, block)
}
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index c8fe1af..ba328e7 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -479,7 +479,7 @@
Goto { target } => propagate(target, exit_state),
Assert { target, unwind, expected: _, msg: _, cond: _ }
- | Drop { target, unwind, place: _ }
+ | Drop { target, unwind, place: _, replace: _ }
| FalseUnwind { real_target: target, unwind } => {
if let UnwindAction::Cleanup(unwind) = unwind {
propagate(unwind, exit_state);
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index 8c85cb5f..b13429d 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -1,3 +1,8 @@
+mir_transform_arithmetic_overflow = this arithmetic operation will overflow
+mir_transform_call_to_unsafe_label = call to unsafe function
+mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
+mir_transform_const_defined_here = `const` item defined here
+
mir_transform_const_modify = attempting to modify a `const` item
.note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified
@@ -6,50 +11,10 @@
.note2 = the mutable reference will refer to this temporary, not the original `const` item
.note3 = mutable reference created due to call to this method
-mir_transform_const_defined_here = `const` item defined here
-
-mir_transform_unaligned_packed_ref = reference to packed field is unaligned
- .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
- .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-mir_transform_unused_unsafe = unnecessary `unsafe` block
- .label = because it's nested under this `unsafe` block
-
-mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
- [true] function or block
- *[false] block
- }
- .not_inherited = items do not inherit unsafety from separate enclosing items
-
-mir_transform_call_to_unsafe_label = call to unsafe function
-mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
-mir_transform_use_of_asm_label = use of inline assembly
-mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
-mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
-mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
mir_transform_const_ptr2int_label = cast of pointer to int
mir_transform_const_ptr2int_note = casting pointers to integers in constants
-mir_transform_use_of_static_mut_label = use of mutable static
-mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-mir_transform_use_of_extern_static_label = use of extern static
-mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
mir_transform_deref_ptr_label = dereference of raw pointer
mir_transform_deref_ptr_note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-mir_transform_union_access_label = access to union field
-mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
-mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
-mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
-mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-mir_transform_target_feature_call_label = call to function with `#[target_feature]`
-mir_transform_target_feature_call_note = can only be called if the required target features are available
-
-mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
-
-mir_transform_arithmetic_overflow = this arithmetic operation will overflow
-mir_transform_operation_will_panic = this operation will panic at runtime
-
mir_transform_ffi_unwind_call = call to {$foreign ->
[true] foreign function
*[false] function pointer
@@ -58,9 +23,45 @@
mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer
.suggestion = cast `{$ident}` to obtain a function pointer
+mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be
.label = the value is held across this suspend point
.note = {$reason}
.help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point
+mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
+mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
+mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
+mir_transform_operation_will_panic = this operation will panic at runtime
+
+mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
+ [true] function or block
+ *[false] block
+ }
+ .not_inherited = items do not inherit unsafety from separate enclosing items
+
mir_transform_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item
+
+mir_transform_target_feature_call_label = call to function with `#[target_feature]`
+mir_transform_target_feature_call_note = can only be called if the required target features are available
+
+mir_transform_unaligned_packed_ref = reference to packed field is unaligned
+ .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
+ .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+mir_transform_union_access_label = access to union field
+mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
+
+mir_transform_unused_unsafe = unnecessary `unsafe` block
+ .label = because it's nested under this `unsafe` block
+
+mir_transform_use_of_asm_label = use of inline assembly
+mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
+mir_transform_use_of_extern_static_label = use of extern static
+mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+mir_transform_use_of_static_mut_label = use of mutable static
+mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index b29ffcc..ef2a0c7 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -80,7 +80,7 @@
is_cleanup: bool,
) {
debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc);
- let TerminatorKind::Drop { ref place, target, unwind } = terminator.kind else {
+ let TerminatorKind::Drop { ref place, target, unwind, replace } = terminator.kind else {
unreachable!();
};
@@ -98,6 +98,11 @@
patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place)));
patch.patch_terminator(
loc.block,
- TerminatorKind::Drop { place: Place::from(temp), target: storage_dead_block, unwind },
+ TerminatorKind::Drop {
+ place: Place::from(temp),
+ target: storage_dead_block,
+ unwind,
+ replace,
+ },
);
}
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index adb09c5..0fe49b8 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -363,7 +363,7 @@
let left_size = self.ecx.layout_of(left_ty).ok()?.size;
let right_size = r.layout.size;
let r_bits = r.to_scalar().to_bits(right_size).ok();
- if r_bits.map_or(false, |b| b >= left_size.bits() as u128) {
+ if r_bits.is_some_and(|b| b >= left_size.bits() as u128) {
debug!("check_binary_op: reporting assert for {:?}", location);
let source_info = self.body().source_info(location);
let panic = AssertKind::Overflow(
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 35e4c24..6a3d425 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -639,7 +639,7 @@
let def_id = mir_source.def_id();
let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans);
- let mut file = create_dump_file(tcx, "html", false, pass_name, &0, mir_body)
+ let mut file = create_dump_file(tcx, "html", false, pass_name, &0i32, mir_body)
.expect("Unexpected error creating MIR spanview HTML file");
let crate_name = tcx.crate_name(def_id.krate);
let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate();
@@ -740,7 +740,7 @@
.join("\n ")
));
}
- let mut file = create_dump_file(tcx, "dot", false, pass_name, &0, mir_body)
+ let mut file = create_dump_file(tcx, "dot", false, pass_name, &0i32, mir_body)
.expect("Unexpected error creating BasicCoverageBlock graphviz DOT file");
graphviz_writer
.write_graphviz(tcx, &mut file)
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 986d2fd..ea1223f 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -9,6 +9,7 @@
use rustc_middle::mir::coverage::*;
use rustc_middle::mir::{self, BasicBlock, BasicBlockData, Terminator, TerminatorKind};
+use std::cmp::Ordering;
use std::ops::{Index, IndexMut};
const ID_SEPARATOR: &str = ",";
@@ -212,8 +213,12 @@
}
#[inline(always)]
- pub fn dominators(&self) -> &Dominators<BasicCoverageBlock> {
- self.dominators.as_ref().unwrap()
+ pub fn rank_partial_cmp(
+ &self,
+ a: BasicCoverageBlock,
+ b: BasicCoverageBlock,
+ ) -> Option<Ordering> {
+ self.dominators.as_ref().unwrap().rank_partial_cmp(a, b)
}
}
@@ -650,26 +655,6 @@
let mut backedges = IndexVec::from_elem_n(Vec::<BasicCoverageBlock>::new(), num_bcbs);
// Identify loops by their backedges.
- //
- // The computational complexity is bounded by: n(s) x d where `n` is the number of
- // `BasicCoverageBlock` nodes (the simplified/reduced representation of the CFG derived from the
- // MIR); `s` is the average number of successors per node (which is most likely less than 2, and
- // independent of the size of the function, so it can be treated as a constant);
- // and `d` is the average number of dominators per node.
- //
- // The average number of dominators depends on the size and complexity of the function, and
- // nodes near the start of the function's control flow graph typically have less dominators
- // than nodes near the end of the CFG. Without doing a detailed mathematical analysis, I
- // think the resulting complexity has the characteristics of O(n log n).
- //
- // The overall complexity appears to be comparable to many other MIR transform algorithms, and I
- // don't expect that this function is creating a performance hot spot, but if this becomes an
- // issue, there may be ways to optimize the `dominates` algorithm (as indicated by an
- // existing `FIXME` comment in that code), or possibly ways to optimize it's usage here, perhaps
- // by keeping track of results for visited `BasicCoverageBlock`s if they can be used to short
- // circuit downstream `dominates` checks.
- //
- // For now, that kind of optimization seems unnecessarily complicated.
for (bcb, _) in basic_coverage_blocks.iter_enumerated() {
for &successor in &basic_coverage_blocks.successors[bcb] {
if basic_coverage_blocks.dominates(successor, bcb) {
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 1493791..d272004 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -344,7 +344,7 @@
// before the dominated equal spans). When later comparing two spans in
// order, the first will either dominate the second, or they will have no
// dominator relationship.
- self.basic_coverage_blocks.dominators().rank_partial_cmp(a.bcb, b.bcb)
+ self.basic_coverage_blocks.rank_partial_cmp(a.bcb, b.bcb)
}
} else {
// Sort hi() in reverse order so shorter spans are attempted after longer spans.
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index 1b3ac78..bf5722b 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -47,7 +47,7 @@
return false;
}
// Check if any of the dominators of the node are also the node's successor.
- doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom))
+ node_data.terminator().successors().any(|succ| doms.dominates(succ, node))
}
fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 98e7a51..fda0e10 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -14,7 +14,7 @@
use rustc_mir_dataflow::MoveDataParamEnv;
use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits};
use rustc_mir_dataflow::{Analysis, ResultsCursor};
-use rustc_span::{DesugaringKind, Span};
+use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
use std::fmt;
@@ -401,7 +401,7 @@
let terminator = data.terminator();
match terminator.kind {
- TerminatorKind::Drop { mut place, target, unwind } => {
+ TerminatorKind::Drop { mut place, target, unwind, replace } => {
if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
place = new_place;
}
@@ -434,10 +434,7 @@
)
}
LookupResult::Parent(..) => {
- if !matches!(
- terminator.source_info.span.desugaring_kind(),
- Some(DesugaringKind::Replace),
- ) {
+ if !replace {
self.tcx.sess.delay_span_bug(
terminator.source_info.span,
format!("drop of untracked value {:?}", bb),
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 891e446..89567ed 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1045,7 +1045,10 @@
for (block, block_data) in body.basic_blocks.iter_enumerated() {
let (target, unwind, source_info) = match block_data.terminator() {
- Terminator { source_info, kind: TerminatorKind::Drop { place, target, unwind } } => {
+ Terminator {
+ source_info,
+ kind: TerminatorKind::Drop { place, target, unwind, replace: _ },
+ } => {
if let Some(local) = place.as_local() {
if local == SELF_ARG {
(target, unwind, source_info)
@@ -1304,6 +1307,7 @@
place: Place::from(SELF_ARG),
target: return_block,
unwind: UnwindAction::Continue,
+ replace: false,
};
let source_info = SourceInfo::outermost(body.span);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 6c2e22a..ca1e209 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -10,7 +10,6 @@
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
-use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_target::spec::abi::Abi;
@@ -450,7 +449,7 @@
checker.visit_basic_block_data(bb, blk);
let term = blk.terminator();
- if let TerminatorKind::Drop { ref place, target, unwind } = term.kind {
+ if let TerminatorKind::Drop { ref place, target, unwind, replace: _ } = term.kind {
work_list.push(target);
// If the place doesn't actually need dropping, treat it like a regular goto.
@@ -458,8 +457,8 @@
.callee
.subst_mir(self.tcx, ty::EarlyBinder(&place.ty(callee_body, tcx).ty));
if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
- work_list.push(unwind);
- }
+ work_list.push(unwind);
+ }
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
&& matches!(term.kind, TerminatorKind::InlineAsm { .. })
{
@@ -551,16 +550,6 @@
// Copy the arguments if needed.
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
- let mut expn_data = ExpnData::default(
- ExpnKind::Inlined,
- callsite.source_info.span,
- self.tcx.sess.edition(),
- None,
- None,
- );
- expn_data.def_site = callee_body.span;
- let expn_data =
- self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx));
let mut integrator = Integrator {
args: &args,
new_locals: Local::new(caller_body.local_decls.len())..,
@@ -572,7 +561,6 @@
cleanup_block: unwind,
in_cleanup_block: false,
tcx: self.tcx,
- expn_data,
always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
};
@@ -956,7 +944,6 @@
cleanup_block: UnwindAction,
in_cleanup_block: bool,
tcx: TyCtxt<'tcx>,
- expn_data: LocalExpnId,
always_live_locals: BitSet<Local>,
}
@@ -1042,11 +1029,6 @@
*scope = self.map_scope(*scope);
}
- fn visit_span(&mut self, span: &mut Span) {
- // Make sure that all spans track the fact that they were inlined.
- *span = span.fresh_expansion(self.expn_data);
- }
-
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data);
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 85b2622..5ce9601 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -108,7 +108,7 @@
// If multiple different locals are copied to the return place. We can't pick a
// single one to rename.
- if copied_to_return_place.map_or(false, |old| old != returned_local) {
+ if copied_to_return_place.is_some_and(|old| old != returned_local) {
return None;
}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 7c47d88..0eb27c2 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -544,6 +544,7 @@
place: dest_field,
target: unwind,
unwind: UnwindAction::Terminate,
+ replace: false,
},
true,
);
@@ -800,6 +801,7 @@
place: rcvr_place(),
target: BasicBlock::new(2),
unwind: UnwindAction::Continue,
+ replace: false,
},
false,
);
@@ -815,6 +817,7 @@
place: rcvr_place(),
target: BasicBlock::new(4),
unwind: UnwindAction::Terminate,
+ replace: false,
},
true,
);
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 2b404ef..e8e4246 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -31,11 +31,11 @@
/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
/// actually compute dominators, we can just compare block indices because bb0 is always the first
/// block, and in any body all other blocks are always dominated by bb0.
-struct SmallDominators {
- inner: Option<Dominators<BasicBlock>>,
+struct SmallDominators<'a> {
+ inner: Option<&'a Dominators<BasicBlock>>,
}
-impl SmallDominators {
+impl SmallDominators<'_> {
fn dominates(&self, first: Location, second: Location) -> bool {
if first.block == second.block {
first.statement_index <= second.statement_index
@@ -198,14 +198,14 @@
Arg,
}
-struct SsaVisitor {
- dominators: SmallDominators,
+struct SsaVisitor<'a> {
+ dominators: SmallDominators<'a>,
assignments: IndexVec<Local, Set1<LocationExtended>>,
assignment_order: Vec<Local>,
direct_uses: IndexVec<Local, u32>,
}
-impl<'tcx> Visitor<'tcx> for SsaVisitor {
+impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
match ctxt {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 6cea6a6..fdd47e6 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,32 +1,32 @@
-monomorphize_recursion_limit =
- reached the recursion limit while instantiating `{$shrunk}`
- .note = `{$def_path_str}` defined here
-
-monomorphize_written_to_path = the full type name has been written to '{$path}'
-
-monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
-
monomorphize_consider_type_length_limit =
consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
-monomorphize_fatal_error = {$error_message}
-
-monomorphize_unknown_partition_strategy = unknown partitioning strategy
-
-monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
-
-monomorphize_unused_generic_params = item has unused generic parameters
-
-monomorphize_large_assignments =
- moving {$size} bytes
- .label = value moved from here
- .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
-
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}
monomorphize_encountered_error_while_instantiating =
the above error was encountered while instantiating `{$formatted_item}`
+monomorphize_fatal_error = {$error_message}
+
+monomorphize_large_assignments =
+ moving {$size} bytes
+ .label = value moved from here
+ .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_recursion_limit =
+ reached the recursion limit while instantiating `{$shrunk}`
+ .note = `{$def_path_str}` defined here
+
+monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+
+monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
+
monomorphize_unknown_cgu_collection_mode =
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
+
+monomorphize_unknown_partition_strategy = unknown partitioning strategy
+
+monomorphize_unused_generic_params = item has unused generic parameters
+
+monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 37b7f6b..603b3dd 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -1,3 +1,4 @@
+use std::cmp;
use std::collections::hash_map::Entry;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -14,10 +15,7 @@
use super::PartitioningCx;
use crate::collector::InliningMap;
-use crate::partitioning::merging;
-use crate::partitioning::{
- MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
-};
+use crate::partitioning::{MonoItemPlacement, Partition, PlacedRootMonoItems};
pub struct DefaultPartitioning;
@@ -26,7 +24,7 @@
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
mono_items: &mut I,
- ) -> PreInliningPartitioning<'tcx>
+ ) -> PlacedRootMonoItems<'tcx>
where
I: Iterator<Item = MonoItem<'tcx>>,
{
@@ -91,38 +89,120 @@
codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
}
- PreInliningPartitioning {
- codegen_units: codegen_units.into_values().collect(),
- roots,
- internalization_candidates,
- }
+ let codegen_units = codegen_units.into_values().collect();
+ PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
}
fn merge_codegen_units(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
) {
- merging::merge_codegen_units(cx, initial_partitioning);
+ assert!(cx.target_cgu_count >= 1);
+
+ // Note that at this point in time the `codegen_units` here may not be
+ // in a deterministic order (but we know they're deterministically the
+ // same set). We want this merging to produce a deterministic ordering
+ // of codegen units from the input.
+ //
+ // Due to basically how we've implemented the merging below (merge the
+ // two smallest into each other) we're sure to start off with a
+ // deterministic order (sorted by name). This'll mean that if two cgus
+ // have the same size the stable sort below will keep everything nice
+ // and deterministic.
+ codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+
+ // This map keeps track of what got merged into what.
+ let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
+ codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
+
+ // Merge the two smallest codegen units until the target size is
+ // reached.
+ while codegen_units.len() > cx.target_cgu_count {
+ // Sort small cgus to the back
+ codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+ let mut smallest = codegen_units.pop().unwrap();
+ let second_smallest = codegen_units.last_mut().unwrap();
+
+ // Move the mono-items from `smallest` to `second_smallest`
+ second_smallest.modify_size_estimate(smallest.size_estimate());
+ for (k, v) in smallest.items_mut().drain() {
+ second_smallest.items_mut().insert(k, v);
+ }
+
+ // Record that `second_smallest` now contains all the stuff that was
+ // in `smallest` before.
+ let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
+ cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
+
+ debug!(
+ "CodegenUnit {} merged into CodegenUnit {}",
+ smallest.name(),
+ second_smallest.name()
+ );
+ }
+
+ let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
+
+ if cx.tcx.sess.opts.incremental.is_some() {
+ // If we are doing incremental compilation, we want CGU names to
+ // reflect the path of the source level module they correspond to.
+ // For CGUs that contain the code of multiple modules because of the
+ // merging done above, we use a concatenation of the names of all
+ // contained CGUs.
+ let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
+ .into_iter()
+ // This `filter` makes sure we only update the name of CGUs that
+ // were actually modified by merging.
+ .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+ .map(|(current_cgu_name, cgu_contents)| {
+ let mut cgu_contents: Vec<&str> =
+ cgu_contents.iter().map(|s| s.as_str()).collect();
+
+ // Sort the names, so things are deterministic and easy to
+ // predict. We are sorting primitive `&str`s here so we can
+ // use unstable sort.
+ cgu_contents.sort_unstable();
+
+ (current_cgu_name, cgu_contents.join("--"))
+ })
+ .collect();
+
+ for cgu in codegen_units.iter_mut() {
+ if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
+ if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
+ cgu.set_name(Symbol::intern(&new_cgu_name));
+ } else {
+ // If we don't require CGU names to be human-readable,
+ // we use a fixed length hash of the composite CGU name
+ // instead.
+ let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
+ cgu.set_name(Symbol::intern(&new_cgu_name));
+ }
+ }
+ }
+ } else {
+ // If we are compiling non-incrementally we just generate simple CGU
+ // names containing an index.
+ for (index, cgu) in codegen_units.iter_mut().enumerate() {
+ let numbered_codegen_unit_name =
+ cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
+ cgu.set_name(numbered_codegen_unit_name);
+ }
+ }
}
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: PreInliningPartitioning<'tcx>,
- ) -> PostInliningPartitioning<'tcx> {
- let mut new_partitioning = Vec::new();
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
let mut mono_item_placements = FxHashMap::default();
- let PreInliningPartitioning {
- codegen_units: initial_cgus,
- roots,
- internalization_candidates,
- } = initial_partitioning;
+ let single_codegen_unit = codegen_units.len() == 1;
- let single_codegen_unit = initial_cgus.len() == 1;
-
- for old_codegen_unit in initial_cgus {
+ for old_codegen_unit in codegen_units.iter_mut() {
// Collect all items that need to be available in this codegen unit.
let mut reachable = FxHashSet::default();
for root in old_codegen_unit.items().keys() {
@@ -174,14 +254,10 @@
}
}
- new_partitioning.push(new_codegen_unit);
+ *old_codegen_unit = new_codegen_unit;
}
- return PostInliningPartitioning {
- codegen_units: new_partitioning,
- mono_item_placements,
- internalization_candidates,
- };
+ return mono_item_placements;
fn follow_inlining<'tcx>(
mono_item: MonoItem<'tcx>,
@@ -201,14 +277,16 @@
fn internalize_symbols(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- partitioning: &mut PostInliningPartitioning<'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
) {
- if partitioning.codegen_units.len() == 1 {
+ if codegen_units.len() == 1 {
// Fast path for when there is only one codegen unit. In this case we
// can internalize all candidates, since there is nowhere else they
// could be accessed from.
- for cgu in &mut partitioning.codegen_units {
- for candidate in &partitioning.internalization_candidates {
+ for cgu in codegen_units {
+ for candidate in &internalization_candidates {
cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
}
}
@@ -225,15 +303,13 @@
}
});
- let mono_item_placements = &partitioning.mono_item_placements;
-
// For each internalization candidates in each codegen unit, check if it is
// accessed from outside its defining codegen unit.
- for cgu in &mut partitioning.codegen_units {
+ for cgu in codegen_units {
let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
for (accessee, linkage_and_visibility) in cgu.items_mut() {
- if !partitioning.internalization_candidates.contains(accessee) {
+ if !internalization_candidates.contains(accessee) {
// This item is no candidate for internalizing, so skip it.
continue;
}
diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs
deleted file mode 100644
index 5c524a1..0000000
--- a/compiler/rustc_monomorphize/src/partitioning/merging.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use std::cmp;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_span::symbol::Symbol;
-
-use super::PartitioningCx;
-use crate::partitioning::PreInliningPartitioning;
-
-pub fn merge_codegen_units<'tcx>(
- cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-) {
- assert!(cx.target_cgu_count >= 1);
- let codegen_units = &mut initial_partitioning.codegen_units;
-
- // Note that at this point in time the `codegen_units` here may not be in a
- // deterministic order (but we know they're deterministically the same set).
- // We want this merging to produce a deterministic ordering of codegen units
- // from the input.
- //
- // Due to basically how we've implemented the merging below (merge the two
- // smallest into each other) we're sure to start off with a deterministic
- // order (sorted by name). This'll mean that if two cgus have the same size
- // the stable sort below will keep everything nice and deterministic.
- codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
-
- // This map keeps track of what got merged into what.
- let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
- codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
-
- // Merge the two smallest codegen units until the target size is reached.
- while codegen_units.len() > cx.target_cgu_count {
- // Sort small cgus to the back
- codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
- let mut smallest = codegen_units.pop().unwrap();
- let second_smallest = codegen_units.last_mut().unwrap();
-
- // Move the mono-items from `smallest` to `second_smallest`
- second_smallest.modify_size_estimate(smallest.size_estimate());
- for (k, v) in smallest.items_mut().drain() {
- second_smallest.items_mut().insert(k, v);
- }
-
- // Record that `second_smallest` now contains all the stuff that was in
- // `smallest` before.
- let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
- cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
-
- debug!(
- "CodegenUnit {} merged into CodegenUnit {}",
- smallest.name(),
- second_smallest.name()
- );
- }
-
- let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-
- if cx.tcx.sess.opts.incremental.is_some() {
- // If we are doing incremental compilation, we want CGU names to
- // reflect the path of the source level module they correspond to.
- // For CGUs that contain the code of multiple modules because of the
- // merging done above, we use a concatenation of the names of
- // all contained CGUs.
- let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
- .into_iter()
- // This `filter` makes sure we only update the name of CGUs that
- // were actually modified by merging.
- .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
- .map(|(current_cgu_name, cgu_contents)| {
- let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
-
- // Sort the names, so things are deterministic and easy to
- // predict.
-
- // We are sorting primitive &strs here so we can use unstable sort
- cgu_contents.sort_unstable();
-
- (current_cgu_name, cgu_contents.join("--"))
- })
- .collect();
-
- for cgu in codegen_units.iter_mut() {
- if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
- if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
- cgu.set_name(Symbol::intern(&new_cgu_name));
- } else {
- // If we don't require CGU names to be human-readable, we
- // use a fixed length hash of the composite CGU name
- // instead.
- let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
- cgu.set_name(Symbol::intern(&new_cgu_name));
- }
- }
- }
- } else {
- // If we are compiling non-incrementally we just generate simple CGU
- // names containing an index.
- for (index, cgu) in codegen_units.iter_mut().enumerate() {
- cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
- }
- }
-}
-
-fn numbered_codegen_unit_name(
- name_builder: &mut CodegenUnitNameBuilder<'_>,
- index: usize,
-) -> Symbol {
- name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
-}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index eafe57a..d0b23ca 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -93,7 +93,6 @@
//! inlining, even when they are not marked `#[inline]`.
mod default;
-mod merging;
use std::cmp;
use std::fs::{self, File};
@@ -129,7 +128,7 @@
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
mono_items: &mut I,
- ) -> PreInliningPartitioning<'tcx>
+ ) -> PlacedRootMonoItems<'tcx>
where
I: Iterator<Item = MonoItem<'tcx>>,
{
@@ -142,12 +141,10 @@
fn merge_codegen_units(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
) {
match self {
- Partitioner::Default(partitioner) => {
- partitioner.merge_codegen_units(cx, initial_partitioning)
- }
+ Partitioner::Default(partitioner) => partitioner.merge_codegen_units(cx, codegen_units),
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
}
}
@@ -155,11 +152,12 @@
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: PreInliningPartitioning<'tcx>,
- ) -> PostInliningPartitioning<'tcx> {
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
match self {
Partitioner::Default(partitioner) => {
- partitioner.place_inlined_mono_items(cx, initial_partitioning)
+ partitioner.place_inlined_mono_items(cx, codegen_units, roots)
}
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
}
@@ -168,48 +166,62 @@
fn internalize_symbols(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
) {
match self {
- Partitioner::Default(partitioner) => {
- partitioner.internalize_symbols(cx, post_inlining_partitioning)
- }
+ Partitioner::Default(partitioner) => partitioner.internalize_symbols(
+ cx,
+ codegen_units,
+ mono_item_placements,
+ internalization_candidates,
+ ),
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
}
}
}
-pub struct PartitioningCx<'a, 'tcx> {
+struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
target_cgu_count: usize,
inlining_map: &'a InliningMap<'tcx>,
}
+pub struct PlacedRootMonoItems<'tcx> {
+ codegen_units: Vec<CodegenUnit<'tcx>>,
+ roots: FxHashSet<MonoItem<'tcx>>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
trait Partition<'tcx> {
fn place_root_mono_items<I>(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
mono_items: &mut I,
- ) -> PreInliningPartitioning<'tcx>
+ ) -> PlacedRootMonoItems<'tcx>
where
I: Iterator<Item = MonoItem<'tcx>>;
fn merge_codegen_units(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
);
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: PreInliningPartitioning<'tcx>,
- ) -> PostInliningPartitioning<'tcx>;
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement>;
fn internalize_symbols(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- partitioning: &mut PostInliningPartitioning<'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
);
}
@@ -225,7 +237,7 @@
}
}
-pub fn partition<'tcx, I>(
+fn partition<'tcx, I>(
tcx: TyCtxt<'tcx>,
mono_items: &mut I,
max_cgu_count: usize,
@@ -241,44 +253,51 @@
// In the first step, we place all regular monomorphizations into their
// respective 'home' codegen unit. Regular monomorphizations are all
// functions and statics defined in the local crate.
- let mut initial_partitioning = {
+ let PlacedRootMonoItems { mut codegen_units, roots, internalization_candidates } = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
partitioner.place_root_mono_items(cx, mono_items)
};
- for cgu in &mut initial_partitioning.codegen_units {
+ for cgu in &mut codegen_units {
cgu.create_size_estimate(tcx);
}
- debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
+ debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
// Merge until we have at most `max_cgu_count` codegen units.
+ // `merge_codegen_units` is responsible for updating the CGU size
+ // estimates.
{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
- partitioner.merge_codegen_units(cx, &mut initial_partitioning);
- debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
+ partitioner.merge_codegen_units(cx, &mut codegen_units);
+ debug_dump(tcx, "POST MERGING", &codegen_units);
}
// In the next step, we use the inlining map to determine which additional
// monomorphizations have to go into each codegen unit. These additional
// monomorphizations can be drop-glue, functions from external crates, and
// local functions the definition of which is marked with `#[inline]`.
- let mut post_inlining = {
+ let mono_item_placements = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
- partitioner.place_inlined_mono_items(cx, initial_partitioning)
+ partitioner.place_inlined_mono_items(cx, &mut codegen_units, roots)
};
- for cgu in &mut post_inlining.codegen_units {
+ for cgu in &mut codegen_units {
cgu.create_size_estimate(tcx);
}
- debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
+ debug_dump(tcx, "POST INLINING", &codegen_units);
// Next we try to make as many symbols "internal" as possible, so LLVM has
// more freedom to optimize.
if !tcx.sess.link_dead_code() {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
- partitioner.internalize_symbols(cx, &mut post_inlining);
+ partitioner.internalize_symbols(
+ cx,
+ &mut codegen_units,
+ mono_item_placements,
+ internalization_candidates,
+ );
}
let instrument_dead_code =
@@ -286,7 +305,7 @@
if instrument_dead_code {
assert!(
- post_inlining.codegen_units.len() > 0,
+ codegen_units.len() > 0,
"There must be at least one CGU that code coverage data can be generated in."
);
@@ -297,7 +316,7 @@
// the object file (CGU) containing the dead function stubs is included
// in the final binary. This will probably require forcing these
// function symbols to be included via `-u` or `/include` linker args.
- let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
+ let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
cgus.sort_by_key(|cgu| cgu.size_estimate());
let dead_code_cgu =
@@ -308,29 +327,17 @@
} else {
// If there are no CGUs that have externally linked items,
// then we just pick the first CGU as a fallback.
- &mut post_inlining.codegen_units[0]
+ &mut codegen_units[0]
};
dead_code_cgu.make_code_coverage_dead_code_cgu();
}
// Finally, sort by codegen unit name, so that we get deterministic results.
- let PostInliningPartitioning {
- codegen_units: mut result,
- mono_item_placements: _,
- internalization_candidates: _,
- } = post_inlining;
+ codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
- result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+ debug_dump(tcx, "FINAL", &codegen_units);
- debug_dump(tcx, "FINAL", &result);
-
- result
-}
-
-pub struct PreInliningPartitioning<'tcx> {
- codegen_units: Vec<CodegenUnit<'tcx>>,
- roots: FxHashSet<MonoItem<'tcx>>,
- internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+ codegen_units
}
/// For symbol internalization, we need to know whether a symbol/mono-item is
@@ -342,12 +349,6 @@
MultipleCgus,
}
-struct PostInliningPartitioning<'tcx> {
- codegen_units: Vec<CodegenUnit<'tcx>>,
- mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
- internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
let dump = move || {
use std::fmt::Write;
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 2d0f466..9263394 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -1,230 +1,298 @@
-parse_struct_literal_body_without_path =
- struct literal body without path
- .suggestion = you might have forgotten to add the struct literal inside the block
-
-parse_struct_literal_needing_parens =
- invalid struct literal
- .suggestion = you might need to surround the struct literal in parentheses
-
-parse_maybe_report_ambiguous_plus =
- ambiguous `+` in a type
- .suggestion = use parentheses to disambiguate
-
-parse_maybe_recover_from_bad_type_plus =
- expected a path on the left-hand side of `+`, not `{$ty}`
-
parse_add_paren = try adding parentheses
-parse_forgot_paren = perhaps you forgot parentheses?
+parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
+ .suggestion = if you meant to call a macro, try
+ .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
-parse_expect_path = expected a path
+parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
+ .suggestion = add parentheses to clarify the precedence
-parse_maybe_recover_from_bad_qpath_stage_2 =
- missing angle brackets in associated item path
- .suggestion = try: `{$ty}`
+parse_array_brackets_instead_of_braces = this is a block expression, not an array
+ .suggestion = to make an array, use square brackets instead of curly braces
-parse_incorrect_semicolon =
- expected item, found `;`
- .suggestion = remove this semicolon
- .help = {$name} declarations are not followed by a semicolon
+parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
-parse_incorrect_use_of_await =
- incorrect use of `await`
- .parentheses_suggestion = `await` is not a method call, remove the parentheses
- .postfix_suggestion = `await` is a postfix operation
+parse_assoc_lifetime = associated lifetimes are not supported
+ .label = the lifetime is given here
+ .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
-parse_in_in_typo =
- expected iterable, found keyword `in`
- .suggestion = remove the duplicated `in`
+parse_associated_static_item_not_allowed = associated `static` items are not allowed
-parse_invalid_variable_declaration =
- invalid variable declaration
+parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
-parse_switch_mut_let_order =
- switch the order of `mut` and `let`
-parse_missing_let_before_mut = missing keyword
-parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
-parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
+ .label = to use `async fn`, switch to Rust 2018 or later
-parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
- .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
- .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
+ .suggestion = try switching the order
-parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
- .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
- .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
- .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
+parse_attr_after_generic = trailing attribute after generic parameter
+ .label = attributes must go before parameters
-parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
- .suggestion = use `!` to perform bitwise not
+parse_attr_without_generics = attribute without generic parameters
+ .label = attributes are only permitted when preceding parameters
-parse_unexpected_if_with_if = unexpected `if` in the condition expression
- .suggestion = remove the `if`
+parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
+ .label = attributes are not allowed here
-parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
-parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
-parse_unexpected_token_after_not_logical = use `!` to perform logical negation
-parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
+parse_bad_assoc_type_bounds = bounds on associated types do not belong here
+ .label = belongs in `where` clause
-parse_malformed_loop_label = malformed loop label
- .suggestion = use the correct loop label format
+parse_bad_item_kind = {$descr} is not supported in {$ctx}
+ .help = consider moving the {$descr} out to a nearby module scope
-parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
- .suggestion = remove the lifetime annotation
- .label = annotated with lifetime here
+parse_bad_return_type_notation_dotdot =
+ return type notation uses `()` instead of `(..)` for elided arguments
+ .suggestion = remove the `..`
-parse_field_expression_with_generic = field expressions cannot have generic arguments
+parse_bad_return_type_notation_output =
+ return type not allowed with return type notation
+ .suggestion = remove the return type
-parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
+parse_bare_cr = {$double_quotes ->
+ [true] bare CR not allowed in string, use `\r` instead
+ *[false] character constant must be escaped: `\r`
+ }
+ .escape = escape the character
-parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
- .suggestion_remove_label = consider removing the label
- .suggestion_enclose_in_block = consider enclosing expression in a block
+parse_bare_cr_in_raw_string = bare CR not allowed in raw string
-parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
- .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
- .label = the label
- .suggestion = add `:` after the label
+parse_binary_float_literal_not_supported = binary float literal is not supported
+parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
-parse_do_catch_syntax_removed = found removed `do catch` syntax
- .note = following RFC #2388, the new non-placeholder syntax is `try`
- .suggestion = replace with the new syntax
+parse_box_not_pat = expected pattern, found {$descr}
+ .note = `box` is a reserved keyword
+ .suggestion = escape `box` to use it as an identifier
-parse_float_literal_requires_integer_part = float literals must have an integer part
- .suggestion = must have an integer part
+parse_box_syntax_removed = `box_syntax` has been removed
+ .suggestion = use `Box::new()` instead
-parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
- .help = valid widths are 8, 16, 32, 64 and 128
-
-parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
- .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
- .suggestion = try making the prefix lowercase
-
-parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
- .label = invalid suffix `{$suffix}`
- .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-
-parse_invalid_float_literal_width = invalid width `{$width}` for float literal
- .help = valid widths are 32 and 64
-
-parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
- .label = invalid suffix `{$suffix}`
- .help = valid suffixes are `f32` and `f64`
-
-parse_int_literal_too_large = integer literal is too large
-
-parse_missing_semicolon_before_array = expected `;`, found `[`
- .suggestion = consider adding `;` here
-
-parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
- .label = the `block` fragment is within this context
-
-parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
- .suggestion = use `..` to fill in the rest of the fields
-
-parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
- .add_then_block = add a block here
- .condition_possibly_unfinished = this binary operation is possibly unfinished
-
-parse_if_expression_missing_condition = missing condition for `if` expression
- .condition_label = expected condition here
- .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
-
-parse_expected_expression_found_let = expected expression, found `let` statement
-
-parse_expect_eq_instead_of_eqeq = expected `=`, found `==`
- .suggestion = consider using `=` here
-
-parse_expected_else_block = expected `{"{"}`, found {$first_tok}
- .label = expected an `if` or a block after this `else`
- .suggestion = add an `if` if this is the condition of a chained `else if` statement
-
-parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
- .branch_label = the attributes are attached to this branch
- .ctx_label = the branch belongs to this `{$ctx}`
- .suggestion = remove the attributes
-
-parse_missing_in_in_for_loop = missing `in` in `for` loop
- .use_in_not_of = try using `in` here instead
- .add_in = try adding `in` here
-
-parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
- .suggestion = try adding an expression to the `for` loop
-
-parse_loop_else = `{$loop_kind}...else` loops are not supported
- .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
- .loop_keyword = `else` is attached to this loop
-
-parse_missing_comma_after_match_arm = expected `,` following `match` arm
- .suggestion = missing a comma here to end this `match` arm
+parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
parse_catch_after_try = keyword `catch` cannot follow a `try` block
.help = try using `match` on the result of the `try` block instead
+parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
+parse_colon_as_semi = statements are terminated with a semicolon
+ .suggestion = use a semicolon instead
+
parse_comma_after_base_struct = cannot use a comma after the base struct
.note = the base struct must always be the last field
.suggestion = remove this comma
-parse_eq_field_init = expected `:`, found `=`
- .suggestion = replace equals symbol with a colon
-
-parse_dotdotdot = unexpected token: `...`
- .suggest_exclusive_range = use `..` for an exclusive range
- .suggest_inclusive_range = or `..=` for an inclusive range
-
-parse_left_arrow_operator = unexpected token: `<-`
- .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
-
-parse_remove_let = expected pattern, found `let`
- .suggestion = remove the unnecessary `let` keyword
-
-parse_use_eq_instead = unexpected `==`
- .suggestion = try using `=` instead
-
-parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
- .suggestion = try using { "`{}`" } instead
-
parse_comparison_interpreted_as_generic =
`<` is interpreted as a start of generic arguments for `{$type}`, not a comparison
.label_args = interpreted as generic arguments
.label_comparison = not interpreted as comparison
.suggestion = try comparing the cast value
-parse_shift_interpreted_as_generic =
- `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
- .label_args = interpreted as generic arguments
- .label_comparison = not interpreted as shift
- .suggestion = try shifting the cast value
+parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
+ .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
+ .sugg_split_comparison = split the comparison into two
+ .sugg_parenthesize = parenthesize the comparison
+parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
+ .suggestion = initialize the variable
+ .help = if you meant to overwrite, remove the `let` binding
+
+parse_const_bounds_missing_tilde = const bounds must start with `~`
+ .suggestion = add `~`
+
+parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
+ .suggestion = enclose the `const` expression in braces
+
+parse_const_global_cannot_be_mutable = const globals cannot be mutable
+ .label = cannot be mutable
+ .suggestion = you might want to declare a static instead
+
+parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
+ .suggestion = remove `let`
+
+parse_cr_doc_comment = bare CR not allowed in {$block ->
+ [true] block doc-comment
+ *[false] doc-comment
+}
+
+parse_default_not_followed_by_item = `default` is not followed by an item
+ .label = the `default` qualifier
+ .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+parse_do_catch_syntax_removed = found removed `do catch` syntax
+ .note = following RFC #2388, the new non-placeholder syntax is `try`
+ .suggestion = replace with the new syntax
+
+parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
+ .help = doc comments must come before what they document, if a comment was intended use `//`
+ .suggestion = missing comma here
+
+parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
+ .label = doc comments are not allowed here
+
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+ .suggestion = to omit remaining fields, use `..`
+
+parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
+ .suggestion = use `..=` instead
+
+parse_dotdotdot = unexpected token: `...`
+ .suggest_exclusive_range = use `..` for an exclusive range
+ .suggest_inclusive_range = or `..=` for an inclusive range
+
+parse_dotdotdot_rest_pattern = unexpected `...`
+ .label = not a valid pattern
+ .suggestion = for a rest pattern, use `..` instead of `...`
+
+parse_double_colon_in_bound = expected `:` followed by trait or lifetime
+ .suggestion = use single colon
+
+parse_dyn_after_mut = `mut` must precede `dyn`
+ .suggestion = place `mut` before `dyn`
+
+parse_empty_exponent_float = expected at least one digit in exponent
+
+parse_empty_unicode_escape = empty unicode escape
+ .label = this escape must have at least 1 hex digit
+
+parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
+
+parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
+ .suggestion = replace `enum struct` with
+
+parse_eq_field_init = expected `:`, found `=`
+ .suggestion = replace equals symbol with a colon
+
+parse_equals_struct_default = default values on `struct` fields aren't supported
+ .suggestion = remove this unsupported default value
+
+parse_escape_only_char = {$byte ->
+ [true] byte
+ *[false] character
+ } constant must be escaped: `{$escaped_msg}`
+ .escape = escape the character
+
+parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
+ .suggestion = use `..` to fill in the rest of the fields
+
+parse_expect_eq_instead_of_eqeq = expected `=`, found `==`
+ .suggestion = consider using `=` here
+
+parse_expect_label_found_ident = expected a label, found an identifier
+ .suggestion = labels start with a tick
+
+parse_expect_path = expected a path
+
+parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
+ .label_lhs = interpreted as a pattern, not a binding
+ .label_rhs = also a pattern
+ .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+parse_expected_builtin_ident = expected identifier after `builtin #`
+
+parse_expected_comma_after_pattern_field = expected `,`
+
+parse_expected_else_block = expected `{"{"}`, found {$first_tok}
+ .label = expected an `if` or a block after this `else`
+ .suggestion = add an `if` if this is the condition of a chained `else if` statement
+
+parse_expected_expression_found_let = expected expression, found `let` statement
+
+parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
+ .suggestion = use `Fn` to refer to the trait
+
+parse_expected_identifier = expected identifier
+
+parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
+parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
+parse_expected_identifier_found_keyword = expected identifier, found keyword
+parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
+parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
+parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
+parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
+parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
+parse_expected_identifier_found_str = expected identifier, found `{$token}`
+
+parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
+ .suggestion = add `mut` or `const` here
+
+parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
+parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
+parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
+parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
+parse_expected_semi_found_str = expected `;`, found `{$token}`
+
+parse_expected_statement_after_outer_attr = expected statement after outer attribute
+
+parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
+
+parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
+ .label = dash-separated idents are not valid
+ .suggestion = if the original crate name uses dashes you need to use underscores in the code
+
+parse_extern_item_cannot_be_const = extern items cannot be `const`
+ .suggestion = try using a static value
+ .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
+
+parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
+ .suggestion = remove the extra `impl`
+ .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
+
+
+parse_field_expression_with_generic = field expressions cannot have generic arguments
+
+parse_float_literal_requires_integer_part = float literals must have an integer part
+ .suggestion = must have an integer part
+
+parse_float_literal_unsupported_base = {$base} float literal is not supported
+
+parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
+ .label = `async` because of this
+ .suggestion = remove the `async` qualifier
+
+parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
+ .label = `const` because of this
+ .suggestion = remove the `const` qualifier
+
+parse_fn_ptr_with_generics = function pointer types may not have generic parameters
+ .suggestion = consider moving the lifetime {$arity ->
+ [one] parameter
+ *[other] parameters
+ } to {$for_param_list_exists ->
+ [true] the
+ *[false] a
+ } `for` parameter list
+
+parse_forgot_paren = perhaps you forgot parentheses?
parse_found_expr_would_be_stmt = expected expression, found `{$token}`
.label = expected expression
-parse_leading_plus_not_supported = leading `+` is not supported
- .label = unexpected `+`
- .suggestion_remove_plus = try removing the `+`
+parse_function_body_equals_expr = function body cannot be `= expression;`
+ .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
-parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
- .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
- .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
+ .suggestion = surround the type parameters with angle brackets
-parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+parse_generics_in_path = unexpected generic arguments in path
-parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+parse_if_expression_missing_condition = missing condition for `if` expression
+ .condition_label = expected condition here
+ .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
-parse_array_brackets_instead_of_braces = this is a block expression, not an array
- .suggestion = to make an array, use square brackets instead of curly braces
+parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
+ .add_then_block = add a block here
+ .condition_possibly_unfinished = this binary operation is possibly unfinished
-parse_match_arm_body_without_braces = `match` arm body without braces
- .label_statements = {$num_statements ->
- [one] this statement is not surrounded by a body
- *[other] these statements are not surrounded by a body
- }
- .label_arrow = while parsing the `match` arm starting here
- .suggestion_add_braces = surround the {$num_statements ->
- [one] statement
- *[other] statements
- } with a body
- .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+parse_in_in_typo =
+ expected iterable, found keyword `in`
+ .suggestion = remove the duplicated `in`
+
+parse_inappropriate_default = {$article} {$descr} cannot be `default`
+ .label = `default` because of this
+ .note = only associated `fn`, `const`, and `type` items can be `default`
parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
.suggestion_remove_eq = use `..=` instead
@@ -238,16 +306,88 @@
.suggestion_open_range = use `..` instead
.note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
-parse_struct_literal_not_allowed_here = struct literals are not allowed here
- .suggestion = surround the struct literal with parentheses
+parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
+ .suggestion = remove the parentheses
+
+parse_incorrect_semicolon =
+ expected item, found `;`
+ .suggestion = remove this semicolon
+ .help = {$name} declarations are not followed by a semicolon
+
+parse_incorrect_use_of_await =
+ incorrect use of `await`
+ .parentheses_suggestion = `await` is not a method call, remove the parentheses
+ .postfix_suggestion = `await` is a postfix operation
+
+parse_incorrect_visibility_restriction = incorrect visibility restriction
+ .help = some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+ .suggestion = make this visible only to module `{$inner_str}` with `in`
+
+parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
+ .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute
+ .label_attr = not permitted following an outer attribute
+ .label_prev_attr = previous outer attribute
+ .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
+ .label_attr = not permitted following an outer doc comment
+ .label_prev_doc_comment = previous doc comment
+ .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_doc_comment_not_permitted = expected outer doc comment
+ .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+ .suggestion = you might have meant to write a regular comment
+ .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
+ .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
+
+parse_int_literal_too_large = integer literal is too large
+
+parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
+ .label = the `block` fragment is within this context
+
+parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
+ .label = {parse_invalid_char_in_escape_msg}
+
+parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
+ [true] numeric character
+ *[false] unicode
+ } escape
+
+parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
+ .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
+ .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+
+parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
+parse_invalid_digit_literal = invalid digit for a base {$base} literal
+
+parse_invalid_dyn_keyword = invalid `dyn` keyword
+ .help = `dyn` is only needed at the start of a trait `+`-separated list
+ .suggestion = remove this keyword
+
+parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
+parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+ .label = invalid suffix `{$suffix}`
+ .help = valid suffixes are `f32` and `f64`
+
+parse_invalid_float_literal_width = invalid width `{$width}` for float literal
+ .help = valid widths are 32 and 64
+
+parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
+
+parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
+ .help = valid widths are 8, 16, 32, 64 and 128
parse_invalid_interpolated_expression = invalid interpolated expression
-parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-parse_octal_float_literal_not_supported = octal float literal is not supported
-parse_binary_float_literal_not_supported = binary float literal is not supported
-parse_not_supported = not supported
-
parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
.label = invalid suffix `{$suffix}`
@@ -257,207 +397,129 @@
.tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
.tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
-parse_expected_builtin_ident = expected identifier after `builtin #`
+parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
+ .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
+ .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
+ .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
-parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
+parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
-parse_non_string_abi_literal = non-string ABI literal
- .suggestion = specify the ABI with a string literal
+parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
+ .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+ .suggestion = try making the prefix lowercase
+
+parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+ .label = invalid suffix `{$suffix}`
+ .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+parse_invalid_unicode_escape = invalid unicode character escape
+ .label = invalid escape
+ .help = unicode escape must {$surrogate ->
+ [true] not be a surrogate
+ *[false] be at most 10FFFF
+ }
+
+parse_invalid_variable_declaration =
+ invalid variable declaration
+
+parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
+ .suggestion = write it in the correct case
+
+parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
+parse_label_unexpected_token = unexpected token
+
+parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
+
+parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+
+parse_leading_plus_not_supported = leading `+` is not supported
+ .label = unexpected `+`
+ .suggestion_remove_plus = try removing the `+`
+
+parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
+parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+
+parse_left_arrow_operator = unexpected token: `<-`
+ .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+
+parse_lifetime_after_mut = lifetime must precede `mut`
+ .suggestion = place the lifetime before `mut`
+
+parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
+ .suggestion = remove the lifetime annotation
+ .label = annotated with lifetime here
+
+parse_lone_slash = invalid trailing slash in literal
+ .label = {parse_lone_slash}
+
+parse_loop_else = `{$loop_kind}...else` loops are not supported
+ .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ .loop_keyword = `else` is attached to this loop
+
+parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
+ .suggestion = remove the visibility
+ .help = try adjusting the macro to put `{$vis}` inside the invocation
+
+parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
+
+parse_macro_name_remove_bang = macro names aren't followed by a `!`
+ .suggestion = remove the `!`
+
+parse_macro_rules_missing_bang = expected `!` after `macro_rules`
+ .suggestion = add a `!`
+
+parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
+ .suggestion = try exporting the macro
+
+parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
+ .suggestion = missing condition and attribute
+ .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+parse_malformed_loop_label = malformed loop label
+ .suggestion = use the correct loop label format
+
+parse_match_arm_body_without_braces = `match` arm body without braces
+ .label_statements = {$num_statements ->
+ [one] this statement is not surrounded by a body
+ *[other] these statements are not surrounded by a body
+ }
+ .label_arrow = while parsing the `match` arm starting here
+ .suggestion_add_braces = surround the {$num_statements ->
+ [one] statement
+ *[other] statements
+ } with a body
+ .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+ .suggestion = replace `fn` with `impl` here
+
+parse_maybe_recover_from_bad_qpath_stage_2 =
+ missing angle brackets in associated item path
+ .suggestion = try: `{$ty}`
+
+parse_maybe_recover_from_bad_type_plus =
+ expected a path on the left-hand side of `+`, not `{$ty}`
+
+parse_maybe_report_ambiguous_plus =
+ ambiguous `+` in a type
+ .suggestion = use parentheses to disambiguate
+
+parse_meta_bad_delim = wrong meta list delimiters
+parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
.label_unmatched = mismatched closing delimiter
.label_opening_candidate = closing delimiter possibly meant for this
.label_unclosed = unclosed delimiter
-parse_incorrect_visibility_restriction = incorrect visibility restriction
- .help = some possible visibility restrictions are:
- `pub(crate)`: visible only on the current crate
- `pub(super)`: visible only in the current module's parent
- `pub(in path::to::module)`: visible only on the specified path
- .suggestion = make this visible only to module `{$inner_str}` with `in`
+parse_missing_comma_after_match_arm = expected `,` following `match` arm
+ .suggestion = missing a comma here to end this `match` arm
-parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
+parse_missing_const_type = missing type for `{$kind}` item
+ .suggestion = provide a type for the item
-parse_expected_statement_after_outer_attr = expected statement after outer attribute
-
-parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
- .help = doc comments must come before what they document, if a comment was intended use `//`
- .suggestion = missing comma here
-
-parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
- .suggestion = remove `let`
-
-parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
-parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
-parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
-
-parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
- .suggestion = initialize the variable
- .help = if you meant to overwrite, remove the `let` binding
-
-parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
- .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
-
-parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
-
-parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
-parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
-
-parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
- .label_attr = not permitted following an outer doc comment
- .label_prev_doc_comment = previous doc comment
- .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
- .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute
- .label_attr = not permitted following an outer attribute
- .label_prev_attr = previous outer attribute
- .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
- .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
- .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
- .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
-parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
-
-parse_inner_doc_comment_not_permitted = expected outer doc comment
- .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
- .suggestion = you might have meant to write a regular comment
- .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
- .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
-
-parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
-parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
-parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
-parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
-parse_expected_identifier_found_str = expected identifier, found `{$token}`
-
-parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
-parse_expected_identifier_found_keyword = expected identifier, found keyword
-parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
-parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
-parse_expected_identifier = expected identifier
-
-parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
-
-parse_sugg_remove_comma = remove this comma
-parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
-
-parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
-parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
-parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
-parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
-parse_expected_semi_found_str = expected `;`, found `{$token}`
-
-parse_sugg_change_this_to_semi = change this to `;`
-parse_sugg_add_semi = add `;` here
-parse_label_unexpected_token = unexpected token
-
-parse_unmatched_angle_brackets = {$num_extra_brackets ->
- [one] unmatched angle bracket
- *[other] unmatched angle brackets
- }
- .suggestion = {$num_extra_brackets ->
- [one] remove extra angle bracket
- *[other] remove extra angle brackets
- }
-
-parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
- .suggestion = surround the type parameters with angle brackets
-
-parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
- .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
- .sugg_split_comparison = split the comparison into two
- .sugg_parenthesize = parenthesize the comparison
-parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
-
-parse_question_mark_in_type = invalid `?` in type
- .label = `?` is only allowed on expressions, not types
- .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
-
-parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
- .suggestion = remove parentheses in `for` loop
-
-parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
- .label = doc comments are not allowed here
-
-parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
- .label = attributes are not allowed here
-
-parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
- .suggestion = give this argument a name or use an underscore to ignore it
-
-parse_self_param_not_first = unexpected `self` parameter in function
- .label = must be the first parameter of an associated function
-
-parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
- .suggestion = enclose the `const` expression in braces
-
-parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
- .label = expected a `const` expression, not a parameter declaration
- .suggestion = `const` parameters must be declared for the `impl`
-
-parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
- .suggestion = the `const` keyword is only needed in the definition of the type
-
-parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
- .suggestion = try switching the order
-
-parse_double_colon_in_bound = expected `:` followed by trait or lifetime
- .suggestion = use single colon
-
-parse_fn_ptr_with_generics = function pointer types may not have generic parameters
- .suggestion = consider moving the lifetime {$arity ->
- [one] parameter
- *[other] parameters
- } to {$for_param_list_exists ->
- [true] the
- *[false] a
- } `for` parameter list
-
-parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
-
-parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
- .suggestion = replace `fn` with `impl` here
-
-parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
- .suggestion = use `Fn` to refer to the trait
-
-parse_path_single_colon = path separator must be a double colon
- .suggestion = use a double colon instead
-
-parse_colon_as_semi = statements are terminated with a semicolon
- .suggestion = use a semicolon instead
-
-parse_type_ascription_removed =
- if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
-
-parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
- .label = unexpected where clause
- .name_label = while parsing this tuple struct
- .body_label = the struct body
- .suggestion = move the body before the where clause
-
-parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
- .label = to use `async fn`, switch to Rust 2018 or later
-
-parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
-
-parse_self_argument_pointer = cannot pass `self` by raw pointer
- .label = cannot pass `self` by raw pointer
-
-parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
- .label = the visibility
- .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
-
-parse_default_not_followed_by_item = `default` is not followed by an item
- .label = the `default` qualifier
- .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
-
-parse_missing_struct_for_struct_definition = missing `struct` for struct definition
- .suggestion = add `struct` here to parse `{$ident}` as a public struct
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+ .suggestion = try adding an expression to the `for` loop
parse_missing_fn_for_function_definition = missing `fn` for function definition
.suggestion = add `fn` here to parse `{$ident}` as a public function
@@ -465,186 +527,29 @@
parse_missing_fn_for_method_definition = missing `fn` for method definition
.suggestion = add `fn` here to parse `{$ident}` as a public method
-parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
- .suggestion = if you meant to call a macro, try
- .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
+parse_missing_for_in_trait_impl = missing `for` in a trait impl
+ .suggestion = add `for` here
+
+parse_missing_in_in_for_loop = missing `in` in `for` loop
+ .use_in_not_of = try using `in` here instead
+ .add_in = try adding `in` here
+
+parse_missing_let_before_mut = missing keyword
+parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
+ .suggestion = add `+`
+
+parse_missing_semicolon_before_array = expected `;`, found `[`
+ .suggestion = consider adding `;` here
+
+parse_missing_struct_for_struct_definition = missing `struct` for struct definition
+ .suggestion = add `struct` here to parse `{$ident}` as a public struct
parse_missing_trait_in_trait_impl = missing trait in a trait impl
.suggestion_add_trait = add a trait here
.suggestion_remove_for = for an inherent impl, drop this `for`
-parse_missing_for_in_trait_impl = missing `for` in a trait impl
- .suggestion = add `for` here
-
-parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
-
-parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
- .suggestion = remove the extra `impl`
- .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
-
-
-parse_non_item_in_item_list = non-item in item list
- .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
- .label_list_start = item list starts here
- .label_non_item = non-item starts here
- .label_list_end = item list ends here
- .suggestion_remove_semicolon = consider removing this semicolon
-
-parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
-
-parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
-parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
-
-parse_associated_static_item_not_allowed = associated `static` items are not allowed
-
-parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
- .label = dash-separated idents are not valid
- .suggestion = if the original crate name uses dashes you need to use underscores in the code
-
-parse_extern_item_cannot_be_const = extern items cannot be `const`
- .suggestion = try using a static value
- .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
-
-parse_const_global_cannot_be_mutable = const globals cannot be mutable
- .label = cannot be mutable
- .suggestion = you might want to declare a static instead
-
-parse_missing_const_type = missing type for `{$kind}` item
- .suggestion = provide a type for the item
-
-parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
- .suggestion = replace `enum struct` with
-
-parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
-parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
-parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
-parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
-
-parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
- .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
-
-parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
- .label = lifetime parameters cannot have default values
-
-parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
- .label = previous `where` clause starts here
- .suggestion = consider joining the two `where` clauses into one
-
-parse_nonterminal_expected_item_keyword = expected an item keyword
-parse_nonterminal_expected_statement = expected a statement
-parse_nonterminal_expected_ident = expected ident, found `{$token}`
-parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
-
-parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
-parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
-parse_sugg_remove_leading_vert_in_pattern = remove the `|`
-parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
-
-parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
-
-parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
- .suggestion = remove the `||`
-
-parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
-
-parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
- .suggestion = use a single `|` to separate multiple alternative patterns
-
-parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
- .suggestion = remove the `{$token}`
-
-parse_dotdotdot_rest_pattern = unexpected `...`
- .label = not a valid pattern
- .suggestion = for a rest pattern, use `..` instead of `...`
-
-parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
- .label_pattern = pattern on the left, should be on the right
- .label_binding = binding on the right, should be on the left
- .suggestion = switch the order
-
-parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
- .label_lhs = interpreted as a pattern, not a binding
- .label_rhs = also a pattern
- .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-
-parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
- .suggestion = add parentheses to clarify the precedence
-
-parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
- .suggestion = remove the lifetime
-
-parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
- .suggestion = try switching the order
-
-parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
- .suggestion = add `mut` to each binding
-parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
- .suggestion = remove the `mut` prefix
-parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
-
-parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
- .suggestion = remove the additional `mut`s
-
-parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
- .suggestion = use `..=` instead
-
-parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
-
-parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
- .suggestion = to omit remaining fields, use `..`
-
-parse_expected_comma_after_pattern_field = expected `,`
-
-parse_return_types_use_thin_arrow = return types are denoted using `->`
- .suggestion = use `->` instead
-
-parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
-
-parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
- .suggestion = add `mut` or `const` here
-
-parse_lifetime_after_mut = lifetime must precede `mut`
- .suggestion = place the lifetime before `mut`
-
-parse_dyn_after_mut = `mut` must precede `dyn`
- .suggestion = place `mut` before `dyn`
-
-parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
- .label = `const` because of this
- .suggestion = remove the `const` qualifier
-
-parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
- .label = `async` because of this
- .suggestion = remove the `async` qualifier
-
-parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
-
-parse_invalid_dyn_keyword = invalid `dyn` keyword
- .help = `dyn` is only needed at the start of a trait `+`-separated list
- .suggestion = remove this keyword
-
-parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-
-parse_unexpected_token_after_dot = unexpected token: `{$actual}`
-
-parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
-
-parse_cr_doc_comment = bare CR not allowed in {$block ->
- [true] block doc-comment
- *[false] doc-comment
-}
-
-parse_no_digits_literal = no valid digits found for number
-
-parse_invalid_digit_literal = invalid digit for a base {$base} literal
-
-parse_empty_exponent_float = expected at least one digit in exponent
-
-parse_float_literal_unsupported_base = {$base} float literal is not supported
+parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
+ .suggestion = remove the `{$sigil}`
parse_more_than_one_char = character literal may only contain one codepoint
.followed_by = this `{$chr}` is followed by the combining {$len ->
@@ -659,73 +564,238 @@
*[false] `str`
} literal, use double quotes
+parse_multiple_skipped_lines = multiple lines skipped by escaped newline
+ .label = skipping everything up to and including this point
+
+parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
+ .label = previous `where` clause starts here
+ .suggestion = consider joining the two `where` clauses into one
+
+parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
+ .suggestion = add `mut` to each binding
+parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
+ .suggestion = remove the `mut` prefix
+parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+
+parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
+ .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
+
+parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
+
parse_no_brace_unicode_escape = incorrect unicode escape sequence
.label = {parse_no_brace_unicode_escape}
.use_braces = format of unicode escape sequences uses braces
.format_of_unicode = format of unicode escape sequences is `\u{"{...}"}`
-parse_invalid_unicode_escape = invalid unicode character escape
- .label = invalid escape
- .help = unicode escape must {$surrogate ->
- [true] not be a surrogate
- *[false] be at most 10FFFF
- }
+parse_no_digits_literal = no valid digits found for number
-parse_escape_only_char = {$byte ->
- [true] byte
- *[false] character
- } constant must be escaped: `{$escaped_msg}`
- .escape = escape the character
+parse_non_item_in_item_list = non-item in item list
+ .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
+ .label_list_start = item list starts here
+ .label_non_item = non-item starts here
+ .label_list_end = item list ends here
+ .suggestion_remove_semicolon = consider removing this semicolon
-parse_bare_cr = {$double_quotes ->
- [true] bare CR not allowed in string, use `\r` instead
- *[false] character constant must be escaped: `\r`
- }
- .escape = escape the character
+parse_non_string_abi_literal = non-string ABI literal
+ .suggestion = specify the ABI with a string literal
-parse_bare_cr_in_raw_string = bare CR not allowed in raw string
+parse_nonterminal_expected_ident = expected ident, found `{$token}`
+parse_nonterminal_expected_item_keyword = expected an item keyword
+parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
-parse_too_short_hex_escape = numeric character escape is too short
+parse_nonterminal_expected_statement = expected a statement
+parse_not_supported = not supported
-parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
- .label = {parse_invalid_char_in_escape_msg}
+parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
- [true] numeric character
- *[false] unicode
- } escape
+parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
+parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
+
+parse_octal_float_literal_not_supported = octal float literal is not supported
+parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
+parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
parse_out_of_range_hex_escape = out of range hex escape
.label = must be a character in the range [\x00-\x7f]
-parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
-parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
+
+parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
+ .branch_label = the attributes are attached to this branch
+ .ctx_label = the branch belongs to this `{$ctx}`
+ .suggestion = remove the attributes
parse_overlong_unicode_escape = overlong unicode escape
.label = must have at most 6 hex digits
+parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
+ .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
+ .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+
+parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
+ .suggestion = remove the parentheses
+
+parse_path_single_colon = path separator must be a double colon
+ .suggestion = use a double colon instead
+
+parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
+ .suggestion = give this argument a name or use an underscore to ignore it
+
+parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
+ .label_pattern = pattern on the left, should be on the right
+ .label_binding = binding on the right, should be on the left
+ .suggestion = switch the order
+
+parse_question_mark_in_type = invalid `?` in type
+ .label = `?` is only allowed on expressions, not types
+ .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
+
+parse_recover_import_as_use = expected item, found {$token_name}
+ .suggestion = items are imported using the `use` keyword
+
+parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
+ .suggestion = try switching the order
+
+parse_remove_let = expected pattern, found `let`
+ .suggestion = remove the unnecessary `let` keyword
+
+parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
+ .suggestion = remove the additional `mut`s
+
+parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
+ .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
+ .label = the label
+ .suggestion = add `:` after the label
+
+parse_return_types_use_thin_arrow = return types are denoted using `->`
+ .suggestion = use `->` instead
+
+parse_self_argument_pointer = cannot pass `self` by raw pointer
+ .label = cannot pass `self` by raw pointer
+
+parse_self_param_not_first = unexpected `self` parameter in function
+ .label = must be the first parameter of an associated function
+
+parse_shift_interpreted_as_generic =
+ `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
+ .label_args = interpreted as generic arguments
+ .label_comparison = not interpreted as shift
+ .suggestion = try shifting the cast value
+
+parse_single_colon_import_path = expected `::`, found `:`
+ .suggestion = use double colon
+ .note = import paths are delimited using `::`
+
+parse_single_colon_struct_type = found single colon in a struct field type path
+ .suggestion = write a path separator here
+
+parse_struct_literal_body_without_path =
+ struct literal body without path
+ .suggestion = you might have forgotten to add the struct literal inside the block
+
+parse_struct_literal_needing_parens =
+ invalid struct literal
+ .suggestion = you might need to surround the struct literal in parentheses
+
+parse_struct_literal_not_allowed_here = struct literals are not allowed here
+ .suggestion = surround the struct literal with parentheses
+
+parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
+ .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
+
+parse_sugg_add_semi = add `;` here
+parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
+
+parse_sugg_change_this_to_semi = change this to `;`
+parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
+
+parse_sugg_remove_comma = remove this comma
+parse_sugg_remove_leading_vert_in_pattern = remove the `|`
+parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+
+parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+
+parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
+
+parse_switch_mut_let_order =
+ switch the order of `mut` and `let`
+parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
+
+parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
+ .suggestion = use `!` to perform bitwise not
+
+parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
+
+parse_too_short_hex_escape = numeric character escape is too short
+
+parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
+ .suggestion = remove the `{$token}`
+
+parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
+parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
+
+parse_type_ascription_removed =
+ if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
+
parse_unclosed_unicode_escape = unterminated unicode escape
.label = missing a closing `{"}"}`
.terminate = terminate the unicode escape
+parse_underscore_literal_suffix = underscore literal suffix is not allowed
+
+parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
+ .suggestion = the `const` keyword is only needed in the definition of the type
+
+parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
+ .label = expected a `const` expression, not a parameter declaration
+ .suggestion = `const` parameters must be declared for the `impl`
+
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+ .label = lifetime parameters cannot have default values
+
+parse_unexpected_if_with_if = unexpected `if` in the condition expression
+ .suggestion = remove the `if`
+
+parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
+ .suggestion = remove the lifetime
+
+parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
+ .suggestion = remove parentheses in `for` loop
+
+parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
+ .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+
+parse_unexpected_token_after_dot = unexpected token: `{$actual}`
+
+parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
+ .suggestion_remove_label = consider removing the label
+ .suggestion_enclose_in_block = consider enclosing expression in a block
+
+parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
+parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
+parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
+
+parse_unexpected_token_after_not_logical = use `!` to perform logical negation
+parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
+parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
+parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
+
+parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
+parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
+parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
+ .suggestion = remove the `||`
+
+parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
+ .suggestion = use a single `|` to separate multiple alternative patterns
+
parse_unicode_escape_in_byte = unicode escape in byte string
.label = {parse_unicode_escape_in_byte}
.help = unicode escape sequences cannot be used as a byte or in a byte string
-parse_empty_unicode_escape = empty unicode escape
- .label = this escape must have at least 1 hex digit
-
-parse_zero_chars = empty character literal
- .label = {parse_zero_chars}
-
-parse_lone_slash = invalid trailing slash in literal
- .label = {parse_lone_slash}
-
-parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
- .label = {parse_unskipped_whitespace}
-
-parse_multiple_skipped_lines = multiple lines skipped by escaped newline
- .label = skipping everything up to and including this point
+parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
parse_unknown_prefix = prefix `{$prefix}` is unknown
.label = unknown prefix
@@ -733,8 +803,6 @@
.suggestion_br = use `br` for a raw byte string
.suggestion_whitespace = consider inserting whitespace here
-parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
-
parse_unknown_start_of_token = unknown start of token: {$escaped}
.sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not
.sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not
@@ -744,94 +812,6 @@
*[other] {$repeats} more times
}
-parse_box_syntax_removed = `box_syntax` has been removed
- .suggestion = use `Box::new()` instead
-
-parse_bad_return_type_notation_output =
- return type not allowed with return type notation
- .suggestion = remove the return type
-
-parse_bad_return_type_notation_dotdot =
- return type notation uses `()` instead of `(..)` for elided arguments
- .suggestion = remove the `..`
-
-parse_bad_assoc_type_bounds = bounds on associated types do not belong here
- .label = belongs in `where` clause
-
-parse_attr_after_generic = trailing attribute after generic parameter
- .label = attributes must go before parameters
-
-parse_attr_without_generics = attribute without generic parameters
- .label = attributes are only permitted when preceding parameters
-
-parse_where_generics = generic parameters on `where` clauses are reserved for future use
- .label = currently unsupported
-
-parse_generics_in_path = unexpected generic arguments in path
-
-parse_assoc_lifetime = associated lifetimes are not supported
- .label = the lifetime is given here
- .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
-
-parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
-
-parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
- .suggestion = remove the `{$sigil}`
-
-parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
- .suggestion = remove the parentheses
-
-parse_const_bounds_missing_tilde = const bounds must start with `~`
- .suggestion = add `~`
-
-parse_underscore_literal_suffix = underscore literal suffix is not allowed
-
-parse_expect_label_found_ident = expected a label, found an identifier
- .suggestion = labels start with a tick
-
-parse_inappropriate_default = {$article} {$descr} cannot be `default`
- .label = `default` because of this
- .note = only associated `fn`, `const`, and `type` items can be `default`
-
-parse_recover_import_as_use = expected item, found {$token_name}
- .suggestion = items are imported using the `use` keyword
-
-parse_single_colon_import_path = expected `::`, found `:`
- .suggestion = use double colon
- .note = import paths are delimited using `::`
-
-parse_bad_item_kind = {$descr} is not supported in {$ctx}
- .help = consider moving the {$descr} out to a nearby module scope
-
-parse_single_colon_struct_type = found single colon in a struct field type path
- .suggestion = write a path separator here
-
-parse_equals_struct_default = default values on `struct` fields aren't supported
- .suggestion = remove this unsupported default value
-
-parse_macro_rules_missing_bang = expected `!` after `macro_rules`
- .suggestion = add a `!`
-
-parse_macro_name_remove_bang = macro names aren't followed by a `!`
- .suggestion = remove the `!`
-
-parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
- .suggestion = try exporting the macro
-
-parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
- .suggestion = remove the visibility
- .help = try adjusting the macro to put `{$vis}` inside the invocation
-
-parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
- .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
-
-parse_function_body_equals_expr = function body cannot be `= expression;`
- .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
-
-parse_box_not_pat = expected pattern, found {$descr}
- .note = `box` is a reserved keyword
- .suggestion = escape `box` to use it as an identifier
-
parse_unmatched_angle = unmatched angle {$plural ->
[true] brackets
*[false] bracket
@@ -841,19 +821,39 @@
*[false] bracket
}
-parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
- .suggestion = add `+`
+parse_unmatched_angle_brackets = {$num_extra_brackets ->
+ [one] unmatched angle bracket
+ *[other] unmatched angle brackets
+ }
+ .suggestion = {$num_extra_brackets ->
+ [one] remove extra angle bracket
+ *[other] remove extra angle brackets
+ }
-parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
- .suggestion = remove the parentheses
+parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
+ .label = {parse_unskipped_whitespace}
-parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
- .suggestion = write it in the correct case
+parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
+ .suggestion = try using { "`{}`" } instead
-parse_meta_bad_delim = wrong meta list delimiters
-parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
-parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
+parse_use_eq_instead = unexpected `==`
+ .suggestion = try using `=` instead
-parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
- .suggestion = missing condition and attribute
- .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
+parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+
+parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
+ .label = the visibility
+ .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+
+parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
+ .label = unexpected where clause
+ .name_label = while parsing this tuple struct
+ .body_label = the struct body
+ .suggestion = move the body before the where clause
+
+parse_where_generics = generic parameters on `where` clauses are reserved for future use
+ .label = currently unsupported
+
+parse_zero_chars = empty character literal
+ .label = {parse_zero_chars}
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index b0ab0f1..1e6ac54 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -72,7 +72,7 @@
// Therefore, the absence of a literal `cfg` or `cfg_attr` guarantees that
// we don't need to do any eager expansion.
attrs.iter().any(|attr| {
- attr.ident().map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
+ attr.ident().is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
})
}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index bcef0f7..c145403 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -845,7 +845,7 @@
//
// `x.foo::<u32>>>(3)`
let parsed_angle_bracket_args =
- segment.args.as_ref().map_or(false, |args| args.is_angle_bracketed());
+ segment.args.as_ref().is_some_and(|args| args.is_angle_bracketed());
debug!(
"check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
@@ -2610,7 +2610,7 @@
let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
let qself_position = qself.as_ref().map(|qself| qself.position);
for (i, segments) in path.segments.windows(2).enumerate() {
- if qself_position.map(|pos| i < pos).unwrap_or(false) {
+ if qself_position.is_some_and(|pos| i < pos) {
continue;
}
if let [a, b] = segments {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ee712a8..1b28f3c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1188,7 +1188,7 @@
// `token.kind` should not be compared here.
// This is because the `snapshot.token.kind` is treated as the same as
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
- self.span_to_snippet(close_paren).map_or(false, |snippet| snippet == ")")
+ self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
{
let mut replacement_err = errors::ParenthesesWithStructFields {
span,
@@ -2078,7 +2078,7 @@
// Therefore, `token.kind` should not be compared here.
if snapshot
.span_to_snippet(snapshot.token.span)
- .map_or(false, |snippet| snippet == "]") =>
+ .is_ok_and(|snippet| snippet == "]") =>
{
return Err(errors::MissingSemicolonBeforeArray {
open_delim: open_delim_span,
@@ -2773,7 +2773,7 @@
// We might have a `=>` -> `=` or `->` typo (issue #89396).
if TokenKind::FatArrow
.similar_tokens()
- .map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind))
+ .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind))
{
err.span_suggestion(
this.token.span,
@@ -3059,7 +3059,7 @@
}
};
- let is_shorthand = parsed_field.as_ref().map_or(false, |f| f.is_shorthand);
+ let is_shorthand = parsed_field.as_ref().is_some_and(|f| f.is_shorthand);
// A shorthand field can be turned into a full field with `:`.
// We should point this out.
self.check_or_expected(!is_shorthand, TokenType::Token(token::Colon));
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index dc18d40..3783ec4 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -699,7 +699,7 @@
// ```
&& self
.span_to_snippet(self.prev_token.span)
- .map_or(false, |snippet| snippet == "}")
+ .is_ok_and(|snippet| snippet == "}")
&& self.token.kind == token::Semi;
let mut semicolon_span = self.token.span;
if !is_unnecessary_semicolon {
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 4068015..7f9222d 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -4,440 +4,66 @@
-passes_see_issue =
see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
-passes_incorrect_do_not_recommend_location =
- `#[do_not_recommend]` can only be placed on trait implementations
-
-passes_outer_crate_level_attr =
- crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-
-passes_inner_crate_level_attr =
- crate-level attribute should be in the root module
-
-passes_ignored_attr_with_macro =
- `#[{$sym}]` is ignored on struct fields, match arms and macro defs
- .warn = {-passes_previously_accepted}
- .note = {-passes_see_issue(issue: "80564")}
-
-passes_ignored_attr =
- `#[{$sym}]` is ignored on struct fields and match arms
- .warn = {-passes_previously_accepted}
- .note = {-passes_see_issue(issue: "80564")}
-
-passes_inline_ignored_function_prototype =
- `#[inline]` is ignored on function prototypes
-
-passes_inline_ignored_constants =
- `#[inline]` is ignored on constants
- .warn = {-passes_previously_accepted}
- .note = {-passes_see_issue(issue: "65833")}
-
-passes_inline_not_fn_or_closure =
- attribute should be applied to function or closure
- .label = not a function or closure
-
-passes_no_coverage_ignored_function_prototype =
- `#[no_coverage]` is ignored on function prototypes
-
-passes_no_coverage_propagate =
- `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
-
-passes_no_coverage_fn_defn =
- `#[no_coverage]` may only be applied to function definitions
-
-passes_no_coverage_not_coverable =
- `#[no_coverage]` must be applied to coverable code
- .label = not coverable code
-
-passes_should_be_applied_to_fn =
- attribute should be applied to a function definition
- .label = {$on_crate ->
- [true] cannot be applied to crates
- *[false] not a function definition
- }
-
-passes_naked_tracked_caller =
- cannot use `#[track_caller]` with `#[naked]`
-
-passes_should_be_applied_to_struct_enum =
- attribute should be applied to a struct or enum
- .label = not a struct or enum
-
-passes_should_be_applied_to_trait =
- attribute should be applied to a trait
- .label = not a trait
-
-passes_target_feature_on_statement =
- {passes_should_be_applied_to_fn}
- .warn = {-passes_previously_accepted}
- .label = {passes_should_be_applied_to_fn.label}
-
-passes_should_be_applied_to_static =
- attribute should be applied to a static
- .label = not a static
-
-passes_doc_expect_str =
- doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
-
-passes_doc_alias_empty =
- {$attr_str} attribute cannot have empty value
-
-passes_doc_alias_bad_char =
- {$char_} character isn't allowed in {$attr_str}
-
-passes_doc_alias_start_end =
- {$attr_str} cannot start or end with ' '
-
-passes_doc_alias_bad_location =
- {$attr_str} isn't allowed on {$location}
-
-passes_doc_alias_not_an_alias =
- {$attr_str} is the same as the item's name
-
-passes_doc_alias_duplicated = doc alias is duplicated
- .label = first defined here
-
-passes_doc_alias_not_string_literal =
- `#[doc(alias("a"))]` expects string literals
-
-passes_doc_alias_malformed =
- doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
-
-passes_doc_keyword_empty_mod =
- `#[doc(keyword = "...")]` should be used on empty modules
-
-passes_doc_keyword_not_mod =
- `#[doc(keyword = "...")]` should be used on modules
-
-passes_doc_keyword_invalid_ident =
- `{$doc_keyword}` is not a valid identifier
-
-passes_doc_fake_variadic_not_valid =
- `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
-
-passes_doc_keyword_only_impl =
- `#[doc(keyword = "...")]` should be used on impl blocks
-
-passes_doc_inline_conflict_first =
- this attribute...
-
-passes_doc_inline_conflict_second =
- {"."}..conflicts with this attribute
-
-passes_doc_inline_conflict =
- conflicting doc inlining attributes
- .help = remove one of the conflicting attributes
-
-passes_doc_inline_only_use =
- this attribute can only be applied to a `use` item
- .label = only applicable on `use` items
- .not_a_use_item_label = not a `use` item
- .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
-
-passes_doc_attr_not_crate_level =
- `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
-
-passes_attr_crate_level =
- this attribute can only be applied at the crate level
- .suggestion = to apply to the crate, use an inner attribute
- .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-
-passes_doc_test_unknown =
- unknown `doc(test)` attribute `{$path}`
-
-passes_doc_test_takes_list =
- `#[doc(test(...)]` takes a list of attributes
-
-passes_doc_cfg_hide_takes_list =
- `#[doc(cfg_hide(...)]` takes a list of attributes
-
-passes_doc_test_unknown_any =
- unknown `doc` attribute `{$path}`
-
-passes_doc_test_unknown_spotlight =
- unknown `doc` attribute `{$path}`
- .note = `doc(spotlight)` was renamed to `doc(notable_trait)`
- .suggestion = use `notable_trait` instead
- .no_op_note = `doc(spotlight)` is now a no-op
-
-passes_doc_test_unknown_include =
- unknown `doc` attribute `{$path}`
- .suggestion = use `doc = include_str!` instead
-
-passes_doc_invalid =
- invalid `doc` attribute
-
-passes_pass_by_value =
- `pass_by_value` attribute should be applied to a struct, enum or type alias
- .label = is not a struct, enum or type alias
-
-passes_allow_incoherent_impl =
- `rustc_allow_incoherent_impl` attribute should be applied to impl items.
- .label = the only currently supported targets are inherent methods
-
-passes_has_incoherent_inherent_impl =
- `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
- .label = only adts, extern types and traits are supported
-
-passes_both_ffi_const_and_pure =
- `#[ffi_const]` function cannot be `#[ffi_pure]`
-
-passes_ffi_pure_invalid_target =
- `#[ffi_pure]` may only be used on foreign functions
-
-passes_ffi_const_invalid_target =
- `#[ffi_const]` may only be used on foreign functions
-
-passes_ffi_returns_twice_invalid_target =
- `#[ffi_returns_twice]` may only be used on foreign functions
-
-passes_must_use_async =
- `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
- .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
-
-passes_must_use_no_effect =
- `#[must_use]` has no effect when applied to {$article} {$target}
-
-passes_must_not_suspend =
- `must_not_suspend` attribute should be applied to a struct, enum, or trait
- .label = is not a struct, enum, or trait
-
-passes_cold =
- {passes_should_be_applied_to_fn}
- .warn = {-passes_previously_accepted}
- .label = {passes_should_be_applied_to_fn.label}
-
-passes_link =
- attribute should be applied to an `extern` block with non-Rust ABI
- .warn = {-passes_previously_accepted}
- .label = not an `extern` block
-
-passes_link_name =
- attribute should be applied to a foreign function or static
- .warn = {-passes_previously_accepted}
- .label = not a foreign function or static
- .help = try `#[link(name = "{$value}")]` instead
-
-passes_no_link =
- attribute should be applied to an `extern crate` item
- .label = not an `extern crate` item
-
-passes_export_name =
- attribute should be applied to a free function, impl method or static
- .label = not a free function, impl method or static
-
-passes_rustc_layout_scalar_valid_range_not_struct =
- attribute should be applied to a struct
- .label = not a struct
-
-passes_rustc_layout_scalar_valid_range_arg =
- expected exactly one integer literal argument
-
-passes_rustc_legacy_const_generics_only =
- #[rustc_legacy_const_generics] functions must only have const generics
- .label = non-const generic parameter
-
-passes_rustc_legacy_const_generics_index =
- #[rustc_legacy_const_generics] must have one index for each generic parameter
- .label = generic parameters
-
-passes_rustc_legacy_const_generics_index_exceed =
- index exceeds number of arguments
- .label = there {$arg_count ->
- [one] is
- *[other] are
- } only {$arg_count} {$arg_count ->
- [one] argument
- *[other] arguments
- }
-
-passes_rustc_legacy_const_generics_index_negative =
- arguments should be non-negative integers
-
-passes_rustc_dirty_clean =
- attribute requires -Z query-dep-graph to be enabled
-
-passes_link_section =
- attribute should be applied to a function or static
- .warn = {-passes_previously_accepted}
- .label = not a function or static
-
-passes_no_mangle_foreign =
- `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
- .warn = {-passes_previously_accepted}
- .label = foreign {$foreign_item_kind}
- .note = symbol names in extern blocks are not mangled
- .suggestion = remove this attribute
-
-passes_no_mangle =
- attribute should be applied to a free function, impl method or static
- .warn = {-passes_previously_accepted}
- .label = not a free function, impl method or static
-
-passes_repr_ident =
- meta item in `repr` must be an identifier
-
-passes_repr_conflicting =
- conflicting representation hints
-
-passes_used_static =
- attribute must be applied to a `static` variable
-
-passes_used_compiler_linker =
- `used(compiler)` and `used(linker)` can't be used together
-
-passes_allow_internal_unstable =
- attribute should be applied to a macro
- .label = not a macro
-
-passes_debug_visualizer_placement =
- attribute should be applied to a module
-
-passes_debug_visualizer_invalid =
- invalid argument
- .note_1 = expected: `natvis_file = "..."`
- .note_2 = OR
- .note_3 = expected: `gdb_script_file = "..."`
-
-passes_debug_visualizer_unreadable =
- couldn't read {$file}: {$error}
-
-passes_rustc_allow_const_fn_unstable =
- attribute should be applied to `const fn`
- .label = not a `const fn`
-
-passes_rustc_std_internal_symbol =
- attribute should be applied to functions or statics
- .label = not a function or static
-
-passes_const_trait =
- attribute should be applied to a trait
-
-passes_stability_promotable =
- attribute cannot be applied to an expression
-
-passes_deprecated =
- attribute is ignored here
-
-passes_macro_use =
- `#[{$name}]` only has an effect on `extern crate` and modules
-
-passes_macro_export =
- `#[macro_export]` only has an effect on macro definitions
-
-passes_plugin_registrar =
- `#[plugin_registrar]` only has an effect on functions
-
-passes_unused_empty_lints_note =
- attribute `{$name}` with an empty list has no effect
-
-passes_unused_no_lints_note =
- attribute `{$name}` without any lints has no effect
-
-passes_unused_default_method_body_const_note =
- `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
-
-passes_unused =
- unused attribute
- .suggestion = remove this attribute
-
-passes_non_exported_macro_invalid_attrs =
- attribute should be applied to function or closure
- .label = not a function or closure
-
-passes_unused_duplicate =
- unused attribute
- .suggestion = remove this attribute
- .note = attribute also specified here
- .warn = {-passes_previously_accepted}
-
-passes_unused_multiple =
- multiple `{$name}` attributes
- .suggestion = remove this attribute
- .note = attribute also specified here
-
-passes_rustc_lint_opt_ty =
- `#[rustc_lint_opt_ty]` should be applied to a struct
- .label = not a struct
-
-passes_rustc_lint_opt_deny_field_access =
- `#[rustc_lint_opt_deny_field_access]` should be applied to a field
- .label = not a field
-
-passes_link_ordinal =
- attribute should be applied to a foreign function or static
- .label = not a foreign function or static
-
-passes_collapse_debuginfo =
- `collapse_debuginfo` attribute should be applied to macro definitions
- .label = not a macro definition
-
-passes_deprecated_annotation_has_no_effect =
- this `#[deprecated]` annotation has no effect
- .suggestion = remove the unnecessary deprecation attribute
-
-passes_unknown_external_lang_item =
- unknown external lang item: `{$lang_item}`
-
-passes_missing_panic_handler =
- `#[panic_handler]` function required, but not found
-
-passes_missing_lang_item =
- language item required, but not found: `{$name}`
- .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
- .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
-
-passes_lang_item_on_incorrect_target =
- `{$name}` language item must be applied to a {$expected_target}
- .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
-
-passes_unknown_lang_item =
- definition of an unknown language item: `{$name}`
- .label = definition of unknown language item `{$name}`
-
-passes_invalid_attr_at_crate_level =
- `{$name}` attribute cannot be used at crate level
- .suggestion = perhaps you meant to use an outer attribute
-
-passes_duplicate_diagnostic_item_in_crate =
- duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
- .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
-
-passes_diagnostic_item_first_defined =
- the diagnostic item is first defined here
-
passes_abi =
abi: {$abi}
passes_align =
align: {$align}
-passes_size =
- size: {$size}
+passes_allow_incoherent_impl =
+ `rustc_allow_incoherent_impl` attribute should be applied to impl items.
+ .label = the only currently supported targets are inherent methods
-passes_homogeneous_aggregate =
- homogeneous_aggregate: {$homogeneous_aggregate}
+passes_allow_internal_unstable =
+ attribute should be applied to a macro
+ .label = not a macro
-passes_layout_of =
- layout_of({$normalized_ty}) = {$ty_layout}
+passes_attr_application_enum =
+ attribute should be applied to an enum
+ .label = not an enum
-passes_unrecognized_field =
- unrecognized field name `{$name}`
+passes_attr_application_struct =
+ attribute should be applied to a struct
+ .label = not a struct
-passes_layout =
- layout error: {$layout_error}
+passes_attr_application_struct_enum_function_method_union =
+ attribute should be applied to a struct, enum, function, associated function, or union
+ .label = not a struct, enum, function, associated function, or union
-passes_feature_stable_twice =
- feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+passes_attr_application_struct_enum_union =
+ attribute should be applied to a struct, enum, or union
+ .label = not a struct, enum, or union
-passes_feature_previously_declared =
- feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+passes_attr_application_struct_union =
+ attribute should be applied to a struct or union
+ .label = not a struct or union
-passes_expr_not_allowed_in_context =
- {$expr} is not allowed in a `{$context}`
+passes_attr_crate_level =
+ this attribute can only be applied at the crate level
+ .suggestion = to apply to the crate, use an inner attribute
+ .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-passes_const_impl_const_trait =
- const `impl`s must be for traits marked with `#[const_trait]`
- .note = this trait must be annotated with `#[const_trait]`
+passes_attr_only_in_functions =
+ `{$attr}` attribute can only be used on functions
+
+passes_attr_only_on_main =
+ `{$attr}` attribute can only be used on `fn main()`
+
+passes_attr_only_on_root_main =
+ `{$attr}` attribute can only be used on root `fn main()`
+
+passes_both_ffi_const_and_pure =
+ `#[ffi_const]` function cannot be `#[ffi_pure]`
+
+passes_break_inside_async_block =
+ `{$name}` inside of an `async` block
+ .label = cannot `{$name}` inside of an `async` block
+ .async_block_label = enclosing `async` block
+
+passes_break_inside_closure =
+ `{$name}` inside of a closure
+ .label = cannot `{$name}` inside of a closure
+ .closure_label = enclosing closure
passes_break_non_loop =
`break` with value from a `{$kind}` loop
@@ -446,105 +72,170 @@
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
+passes_cannot_inline_naked_function =
+ naked functions cannot be inlined
+
+passes_cannot_stabilize_deprecated =
+ an API can't be stabilized after it is deprecated
+ .label = invalid version
+ .item = the stability attribute annotates this item
+
+passes_change_fields_to_be_of_unit_type =
+ consider changing the { $num ->
+ [one] field
+ *[other] fields
+ } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
+ [one] field
+ *[other] fields
+ }
+
+passes_cold =
+ {passes_should_be_applied_to_fn}
+ .warn = {-passes_previously_accepted}
+ .label = {passes_should_be_applied_to_fn.label}
+
+passes_collapse_debuginfo =
+ `collapse_debuginfo` attribute should be applied to macro definitions
+ .label = not a macro definition
+
+passes_const_impl_const_trait =
+ const `impl`s must be for traits marked with `#[const_trait]`
+ .note = this trait must be annotated with `#[const_trait]`
+
+passes_const_trait =
+ attribute should be applied to a trait
+
passes_continue_labeled_block =
`continue` pointing to a labeled block
.label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to
-passes_break_inside_closure =
- `{$name}` inside of a closure
- .label = cannot `{$name}` inside of a closure
- .closure_label = enclosing closure
+passes_dead_codes =
+ { $multiple ->
+ *[true] multiple {$descr}s are
+ [false] { $num ->
+ [one] {$descr} {$name_list} is
+ *[other] {$descr}s {$name_list} are
+ }
+ } never {$participle}
-passes_break_inside_async_block =
- `{$name}` inside of an `async` block
- .label = cannot `{$name}` inside of an `async` block
- .async_block_label = enclosing `async` block
+passes_debug_visualizer_invalid =
+ invalid argument
+ .note_1 = expected: `natvis_file = "..."`
+ .note_2 = OR
+ .note_3 = expected: `gdb_script_file = "..."`
-passes_outside_loop =
- `{$name}` outside of a loop{$is_break ->
- [true] {" or labeled block"}
- *[false] {""}
- }
- .label = cannot `{$name}` outside of a loop{$is_break ->
- [true] {" or labeled block"}
- *[false] {""}
- }
+passes_debug_visualizer_placement =
+ attribute should be applied to a module
-passes_unlabeled_in_labeled_block =
- unlabeled `{$cf_type}` inside of a labeled block
- .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+passes_debug_visualizer_unreadable =
+ couldn't read {$file}: {$error}
-passes_unlabeled_cf_in_while_condition =
- `break` or `continue` with no label in the condition of a `while` loop
- .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+passes_deprecated =
+ attribute is ignored here
-passes_cannot_inline_naked_function =
- naked functions cannot be inlined
+passes_deprecated_annotation_has_no_effect =
+ this `#[deprecated]` annotation has no effect
+ .suggestion = remove the unnecessary deprecation attribute
-passes_undefined_naked_function_abi =
- Rust ABI is unsupported in naked functions
+passes_deprecated_attribute =
+ deprecated attribute must be paired with either stable or unstable attribute
-passes_no_patterns =
- patterns not allowed in naked function parameters
+passes_diagnostic_item_first_defined =
+ the diagnostic item is first defined here
-passes_params_not_allowed =
- referencing function parameters is not allowed in naked functions
- .help = follow the calling convention in asm block to use parameters
+passes_doc_alias_bad_char =
+ {$char_} character isn't allowed in {$attr_str}
-passes_naked_functions_asm_block =
- naked functions must contain a single asm block
- .label_multiple_asm = multiple asm blocks are unsupported in naked functions
- .label_non_asm = non-asm is unsupported in naked functions
+passes_doc_alias_bad_location =
+ {$attr_str} isn't allowed on {$location}
-passes_naked_functions_operands =
- only `const` and `sym` operands are supported in naked functions
+passes_doc_alias_duplicated = doc alias is duplicated
+ .label = first defined here
-passes_naked_functions_asm_options =
- asm options unsupported in naked functions: {$unsupported_options}
+passes_doc_alias_empty =
+ {$attr_str} attribute cannot have empty value
-passes_naked_functions_must_use_noreturn =
- asm in naked functions must use `noreturn` option
- .suggestion = consider specifying that the asm block is responsible for returning from the function
+passes_doc_alias_malformed =
+ doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
-passes_attr_only_on_main =
- `{$attr}` attribute can only be used on `fn main()`
+passes_doc_alias_not_an_alias =
+ {$attr_str} is the same as the item's name
-passes_attr_only_on_root_main =
- `{$attr}` attribute can only be used on root `fn main()`
+passes_doc_alias_not_string_literal =
+ `#[doc(alias("a"))]` expects string literals
-passes_attr_only_in_functions =
- `{$attr}` attribute can only be used on functions
+passes_doc_alias_start_end =
+ {$attr_str} cannot start or end with ' '
-passes_multiple_rustc_main =
- multiple functions with a `#[rustc_main]` attribute
- .first = first `#[rustc_main]` function
- .additional = additional `#[rustc_main]` function
+passes_doc_attr_not_crate_level =
+ `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
-passes_multiple_start_functions =
- multiple `start` functions
- .label = multiple `start` functions
- .previous = previous `#[start]` function here
+passes_doc_cfg_hide_takes_list =
+ `#[doc(cfg_hide(...)]` takes a list of attributes
-passes_extern_main =
- the `main` function cannot be declared in an `extern` block
+passes_doc_expect_str =
+ doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
-passes_unix_sigpipe_values =
- valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+passes_doc_fake_variadic_not_valid =
+ `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
-passes_no_main_function =
- `main` function not found in crate `{$crate_name}`
- .here_is_main = here is a function named `main`
- .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
- .consider_moving_main = consider moving the `main` function definitions
- .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
- [true] {" "}(in `{$filename}`)
- *[false] {""}
- }
- .consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
- .consider_adding_main_at_crate = consider adding a `main` function at the crate level
- .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
- .non_function_main = non-function item at `crate::main` is found
+passes_doc_inline_conflict =
+ conflicting doc inlining attributes
+ .help = remove one of the conflicting attributes
+
+passes_doc_inline_conflict_first =
+ this attribute...
+
+passes_doc_inline_conflict_second =
+ {"."}..conflicts with this attribute
+
+passes_doc_inline_only_use =
+ this attribute can only be applied to a `use` item
+ .label = only applicable on `use` items
+ .not_a_use_item_label = not a `use` item
+ .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+passes_doc_invalid =
+ invalid `doc` attribute
+
+passes_doc_keyword_empty_mod =
+ `#[doc(keyword = "...")]` should be used on empty modules
+
+passes_doc_keyword_invalid_ident =
+ `{$doc_keyword}` is not a valid identifier
+
+passes_doc_keyword_not_mod =
+ `#[doc(keyword = "...")]` should be used on modules
+
+passes_doc_keyword_only_impl =
+ `#[doc(keyword = "...")]` should be used on impl blocks
+
+passes_doc_test_takes_list =
+ `#[doc(test(...)]` takes a list of attributes
+
+passes_doc_test_unknown =
+ unknown `doc(test)` attribute `{$path}`
+
+passes_doc_test_unknown_any =
+ unknown `doc` attribute `{$path}`
+
+passes_doc_test_unknown_include =
+ unknown `doc` attribute `{$path}`
+ .suggestion = use `doc = include_str!` instead
+
+passes_doc_test_unknown_spotlight =
+ unknown `doc` attribute `{$path}`
+ .note = `doc(spotlight)` was renamed to `doc(notable_trait)`
+ .suggestion = use `notable_trait` instead
+ .no_op_note = `doc(spotlight)` is now a no-op
+
+passes_duplicate_diagnostic_item_in_crate =
+ duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
+ .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
+
+passes_duplicate_feature_err =
+ the feature `{$feature}` has already been declared
passes_duplicate_lang_item =
found duplicate lang item `{$lang_item_name}`
@@ -576,6 +267,66 @@
.first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
.second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+passes_export_name =
+ attribute should be applied to a free function, impl method or static
+ .label = not a free function, impl method or static
+
+passes_expr_not_allowed_in_context =
+ {$expr} is not allowed in a `{$context}`
+
+passes_extern_main =
+ the `main` function cannot be declared in an `extern` block
+
+passes_feature_only_on_nightly =
+ `#![feature]` may not be used on the {$release_channel} release channel
+
+passes_feature_previously_declared =
+ feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+
+passes_feature_stable_twice =
+ feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+
+passes_ffi_const_invalid_target =
+ `#[ffi_const]` may only be used on foreign functions
+
+passes_ffi_pure_invalid_target =
+ `#[ffi_pure]` may only be used on foreign functions
+
+passes_ffi_returns_twice_invalid_target =
+ `#[ffi_returns_twice]` may only be used on foreign functions
+
+passes_has_incoherent_inherent_impl =
+ `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
+ .label = only adts, extern types and traits are supported
+
+passes_homogeneous_aggregate =
+ homogeneous_aggregate: {$homogeneous_aggregate}
+
+passes_ignored_attr =
+ `#[{$sym}]` is ignored on struct fields and match arms
+ .warn = {-passes_previously_accepted}
+ .note = {-passes_see_issue(issue: "80564")}
+
+passes_ignored_attr_with_macro =
+ `#[{$sym}]` is ignored on struct fields, match arms and macro defs
+ .warn = {-passes_previously_accepted}
+ .note = {-passes_see_issue(issue: "80564")}
+
+passes_ignored_derived_impls =
+ `{$name}` has {$trait_list_len ->
+ [one] a derived impl
+ *[other] derived impls
+ } for the {$trait_list_len ->
+ [one] trait {$trait_list}, but this is
+ *[other] traits {$trait_list}, but these are
+ } intentionally ignored during dead code analysis
+
+passes_implied_feature_not_exist =
+ feature `{$implied_by}` implying `{$feature}` does not exist
+
+passes_incorrect_do_not_recommend_location =
+ `#[do_not_recommend]` can only be placed on trait implementations
+
passes_incorrect_target =
`{$name}` language item must be applied to a {$kind} with {$at_least ->
[true] at least {$num}
@@ -589,11 +340,189 @@
*[other] arguments
}
-passes_useless_assignment =
- useless assignment of {$is_field_assign ->
- [true] field
- *[false] variable
- } of type `{$ty}` to itself
+passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
+ .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
+
+passes_inline_ignored_constants =
+ `#[inline]` is ignored on constants
+ .warn = {-passes_previously_accepted}
+ .note = {-passes_see_issue(issue: "65833")}
+
+passes_inline_ignored_function_prototype =
+ `#[inline]` is ignored on function prototypes
+
+passes_inline_not_fn_or_closure =
+ attribute should be applied to function or closure
+ .label = not a function or closure
+
+passes_inner_crate_level_attr =
+ crate-level attribute should be in the root module
+
+passes_invalid_attr_at_crate_level =
+ `{$name}` attribute cannot be used at crate level
+ .suggestion = perhaps you meant to use an outer attribute
+
+passes_invalid_deprecation_version =
+ invalid deprecation version found
+ .label = invalid deprecation version
+ .item = the stability attribute annotates this item
+
+passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+
+passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
+
+passes_invalid_stability =
+ invalid stability version found
+ .label = invalid stability version
+ .item = the stability attribute annotates this item
+
+passes_lang_item_on_incorrect_target =
+ `{$name}` language item must be applied to a {$expected_target}
+ .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
+
+passes_layout =
+ layout error: {$layout_error}
+
+passes_layout_of =
+ layout_of({$normalized_ty}) = {$ty_layout}
+
+passes_link =
+ attribute should be applied to an `extern` block with non-Rust ABI
+ .warn = {-passes_previously_accepted}
+ .label = not an `extern` block
+
+passes_link_name =
+ attribute should be applied to a foreign function or static
+ .warn = {-passes_previously_accepted}
+ .label = not a foreign function or static
+ .help = try `#[link(name = "{$value}")]` instead
+
+passes_link_ordinal =
+ attribute should be applied to a foreign function or static
+ .label = not a foreign function or static
+
+passes_link_section =
+ attribute should be applied to a function or static
+ .warn = {-passes_previously_accepted}
+ .label = not a function or static
+
+passes_macro_export =
+ `#[macro_export]` only has an effect on macro definitions
+
+passes_macro_use =
+ `#[{$name}]` only has an effect on `extern crate` and modules
+
+passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
+passes_missing_const_err =
+ attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ .help = make the function or method const
+ .label = attribute specified here
+
+passes_missing_const_stab_attr =
+ {$descr} has missing const stability attribute
+
+passes_missing_lang_item =
+ language item required, but not found: `{$name}`
+ .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
+ .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
+
+passes_missing_panic_handler =
+ `#[panic_handler]` function required, but not found
+
+passes_missing_stability_attr =
+ {$descr} has missing stability attribute
+
+passes_multiple_rustc_main =
+ multiple functions with a `#[rustc_main]` attribute
+ .first = first `#[rustc_main]` function
+ .additional = additional `#[rustc_main]` function
+
+passes_multiple_start_functions =
+ multiple `start` functions
+ .label = multiple `start` functions
+ .previous = previous `#[start]` function here
+
+passes_must_not_suspend =
+ `must_not_suspend` attribute should be applied to a struct, enum, or trait
+ .label = is not a struct, enum, or trait
+
+passes_must_use_async =
+ `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
+ .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
+
+passes_must_use_no_effect =
+ `#[must_use]` has no effect when applied to {$article} {$target}
+
+passes_naked_functions_asm_block =
+ naked functions must contain a single asm block
+ .label_multiple_asm = multiple asm blocks are unsupported in naked functions
+ .label_non_asm = non-asm is unsupported in naked functions
+
+passes_naked_functions_asm_options =
+ asm options unsupported in naked functions: {$unsupported_options}
+
+passes_naked_functions_must_use_noreturn =
+ asm in naked functions must use `noreturn` option
+ .suggestion = consider specifying that the asm block is responsible for returning from the function
+
+passes_naked_functions_operands =
+ only `const` and `sym` operands are supported in naked functions
+
+passes_naked_tracked_caller =
+ cannot use `#[track_caller]` with `#[naked]`
+
+passes_no_coverage_fn_defn =
+ `#[no_coverage]` may only be applied to function definitions
+
+passes_no_coverage_ignored_function_prototype =
+ `#[no_coverage]` is ignored on function prototypes
+
+passes_no_coverage_not_coverable =
+ `#[no_coverage]` must be applied to coverable code
+ .label = not coverable code
+
+passes_no_coverage_propagate =
+ `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
+
+passes_no_link =
+ attribute should be applied to an `extern crate` item
+ .label = not an `extern crate` item
+
+passes_no_main_function =
+ `main` function not found in crate `{$crate_name}`
+ .here_is_main = here is a function named `main`
+ .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
+ .consider_moving_main = consider moving the `main` function definitions
+ .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
+ [true] {" "}(in `{$filename}`)
+ *[false] {""}
+ }
+ .consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
+ .consider_adding_main_at_crate = consider adding a `main` function at the crate level
+ .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
+ .non_function_main = non-function item at `crate::main` is found
+
+passes_no_mangle =
+ attribute should be applied to a free function, impl method or static
+ .warn = {-passes_previously_accepted}
+ .label = not a free function, impl method or static
+
+passes_no_mangle_foreign =
+ `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
+ .warn = {-passes_previously_accepted}
+ .label = foreign {$foreign_item_kind}
+ .note = symbol names in extern blocks are not mangled
+ .suggestion = remove this attribute
+
+passes_no_patterns =
+ patterns not allowed in naked function parameters
+
+passes_non_exported_macro_invalid_attrs =
+ attribute should be applied to function or closure
+ .label = not a function or closure
+
+passes_object_lifetime_err =
+ {$repr}
passes_only_has_effect_on =
`#[{$attr_name}]` only has an effect on {$target_name ->
@@ -603,103 +532,22 @@
*[unspecified] (unspecified--this is a compiler bug)
}
-passes_object_lifetime_err =
- {$repr}
+passes_outer_crate_level_attr =
+ crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-passes_unrecognized_repr_hint =
- unrecognized representation hint
- .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-
-passes_attr_application_enum =
- attribute should be applied to an enum
- .label = not an enum
-
-passes_attr_application_struct =
- attribute should be applied to a struct
- .label = not a struct
-
-passes_attr_application_struct_union =
- attribute should be applied to a struct or union
- .label = not a struct or union
-
-passes_attr_application_struct_enum_union =
- attribute should be applied to a struct, enum, or union
- .label = not a struct, enum, or union
-
-passes_attr_application_struct_enum_function_method_union =
- attribute should be applied to a struct, enum, function, associated function, or union
- .label = not a struct, enum, function, associated function, or union
-
-passes_transparent_incompatible =
- transparent {$target} cannot have other repr hints
-
-passes_deprecated_attribute =
- deprecated attribute must be paired with either stable or unstable attribute
-
-passes_useless_stability =
- this stability annotation is useless
- .label = useless stability annotation
- .item = the stability attribute annotates this item
-
-passes_invalid_stability =
- invalid stability version found
- .label = invalid stability version
- .item = the stability attribute annotates this item
-
-passes_cannot_stabilize_deprecated =
- an API can't be stabilized after it is deprecated
- .label = invalid version
- .item = the stability attribute annotates this item
-
-passes_invalid_deprecation_version =
- invalid deprecation version found
- .label = invalid deprecation version
- .item = the stability attribute annotates this item
-
-passes_missing_stability_attr =
- {$descr} has missing stability attribute
-
-passes_missing_const_stab_attr =
- {$descr} has missing const stability attribute
-
-passes_trait_impl_const_stable =
- trait implementations cannot be const stable yet
- .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
-
-passes_feature_only_on_nightly =
- `#![feature]` may not be used on the {$release_channel} release channel
-
-passes_unknown_feature =
- unknown feature `{$feature}`
-
-passes_implied_feature_not_exist =
- feature `{$implied_by}` implying `{$feature}` does not exist
-
-passes_duplicate_feature_err =
- the feature `{$feature}` has already been declared
-
-passes_missing_const_err =
- attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
- .help = make the function or method const
- .label = attribute specified here
-
-passes_dead_codes =
- { $multiple ->
- *[true] multiple {$descr}s are
- [false] { $num ->
- [one] {$descr} {$name_list} is
- *[other] {$descr}s {$name_list} are
- }
- } never {$participle}
-
-passes_change_fields_to_be_of_unit_type =
- consider changing the { $num ->
- [one] field
- *[other] fields
- } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
- [one] field
- *[other] fields
+passes_outside_loop =
+ `{$name}` outside of a loop{$is_break ->
+ [true] {" or labeled block"}
+ *[false] {""}
}
+ .label = cannot `{$name}` outside of a loop{$is_break ->
+ [true] {" or labeled block"}
+ *[false] {""}
+ }
+
+passes_params_not_allowed =
+ referencing function parameters is not allowed in naked functions
+ .help = follow the calling convention in asm block to use parameters
passes_parent_info =
{$num ->
@@ -707,48 +555,154 @@
*[other] {$descr}s
} in this {$parent_descr}
-passes_ignored_derived_impls =
- `{$name}` has {$trait_list_len ->
- [one] a derived impl
- *[other] derived impls
- } for the {$trait_list_len ->
- [one] trait {$trait_list}, but this is
- *[other] traits {$trait_list}, but these are
- } intentionally ignored during dead code analysis
+passes_pass_by_value =
+ `pass_by_value` attribute should be applied to a struct, enum or type alias
+ .label = is not a struct, enum or type alias
+
+passes_plugin_registrar =
+ `#[plugin_registrar]` only has an effect on functions
passes_proc_macro_bad_sig = {$kind} has incorrect signature
+passes_repr_conflicting =
+ conflicting representation hints
+
+passes_repr_ident =
+ meta item in `repr` must be an identifier
+
+passes_rustc_allow_const_fn_unstable =
+ attribute should be applied to `const fn`
+ .label = not a `const fn`
+
+passes_rustc_dirty_clean =
+ attribute requires -Z query-dep-graph to be enabled
+
+passes_rustc_layout_scalar_valid_range_arg =
+ expected exactly one integer literal argument
+
+passes_rustc_layout_scalar_valid_range_not_struct =
+ attribute should be applied to a struct
+ .label = not a struct
+
+passes_rustc_legacy_const_generics_index =
+ #[rustc_legacy_const_generics] must have one index for each generic parameter
+ .label = generic parameters
+
+passes_rustc_legacy_const_generics_index_exceed =
+ index exceeds number of arguments
+ .label = there {$arg_count ->
+ [one] is
+ *[other] are
+ } only {$arg_count} {$arg_count ->
+ [one] argument
+ *[other] arguments
+ }
+
+passes_rustc_legacy_const_generics_index_negative =
+ arguments should be non-negative integers
+
+passes_rustc_legacy_const_generics_only =
+ #[rustc_legacy_const_generics] functions must only have const generics
+ .label = non-const generic parameter
+
+passes_rustc_lint_opt_deny_field_access =
+ `#[rustc_lint_opt_deny_field_access]` should be applied to a field
+ .label = not a field
+
+passes_rustc_lint_opt_ty =
+ `#[rustc_lint_opt_ty]` should be applied to a struct
+ .label = not a struct
+
+passes_rustc_std_internal_symbol =
+ attribute should be applied to functions or statics
+ .label = not a function or static
+
+passes_should_be_applied_to_fn =
+ attribute should be applied to a function definition
+ .label = {$on_crate ->
+ [true] cannot be applied to crates
+ *[false] not a function definition
+ }
+
+passes_should_be_applied_to_static =
+ attribute should be applied to a static
+ .label = not a static
+
+passes_should_be_applied_to_struct_enum =
+ attribute should be applied to a struct or enum
+ .label = not a struct or enum
+
+passes_should_be_applied_to_trait =
+ attribute should be applied to a trait
+ .label = not a trait
+
+passes_size =
+ size: {$size}
+
passes_skipping_const_checks = skipping const checks
-passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+passes_stability_promotable =
+ attribute cannot be applied to an expression
-passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
+passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
+
+passes_target_feature_on_statement =
+ {passes_should_be_applied_to_fn}
+ .warn = {-passes_previously_accepted}
+ .label = {passes_should_be_applied_to_fn.label}
+
+passes_trait_impl_const_stable =
+ trait implementations cannot be const stable yet
+ .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+
+passes_transparent_incompatible =
+ transparent {$target} cannot have other repr hints
+
+passes_undefined_naked_function_abi =
+ Rust ABI is unsupported in naked functions
+
+passes_unix_sigpipe_values =
+ valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+
+passes_unknown_external_lang_item =
+ unknown external lang item: `{$lang_item}`
+
+passes_unknown_feature =
+ unknown feature `{$feature}`
+
+passes_unknown_lang_item =
+ definition of an unknown language item: `{$name}`
+ .label = definition of unknown language item `{$name}`
+
+passes_unlabeled_cf_in_while_condition =
+ `break` or `continue` with no label in the condition of a `while` loop
+ .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+
+passes_unlabeled_in_labeled_block =
+ unlabeled `{$cf_type}` inside of a labeled block
+ .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+
+passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
+ .suggestion = if you are using features which are still unstable, change to using `{$implies}`
+ .suggestion_remove = if you are using features which are now stable, remove this line
+
+passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
passes_unreachable_due_to_uninhabited = unreachable {$descr}
.label = unreachable {$descr}
.label_orig = any code following this expression is unreachable
.note = this expression has type `{$ty}`, which is uninhabited
-passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
- .help = did you mean to capture by reference instead?
+passes_unrecognized_field =
+ unrecognized field name `{$name}`
-passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
- .help = did you mean to capture by reference instead?
+passes_unrecognized_repr_hint =
+ unrecognized representation hint
+ .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-passes_unused_var_remove_field = unused variable: `{$name}`
-passes_unused_var_remove_field_suggestion = try removing the field
-
-passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
- .note = consider using `_{$name}` instead
-
-passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
-
-passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
- .suggestion = if you are using features which are still unstable, change to using `{$implies}`
- .suggestion_remove = if you are using features which are now stable, remove this line
-
-passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
- .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
+passes_unused =
+ unused attribute
+ .suggestion = remove this attribute
passes_unused_assign = value assigned to `{$name}` is never read
.help = maybe it is overwritten before being read?
@@ -756,12 +710,58 @@
passes_unused_assign_passed = value passed to `{$name}` is never read
.help = maybe it is overwritten before being read?
-passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
-passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
+passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
+ .help = did you mean to capture by reference instead?
+
+passes_unused_default_method_body_const_note =
+ `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
+
+passes_unused_duplicate =
+ unused attribute
+ .suggestion = remove this attribute
+ .note = attribute also specified here
+ .warn = {-passes_previously_accepted}
+
+passes_unused_empty_lints_note =
+ attribute `{$name}` with an empty list has no effect
+
+passes_unused_multiple =
+ multiple `{$name}` attributes
+ .suggestion = remove this attribute
+ .note = attribute also specified here
+
+passes_unused_no_lints_note =
+ attribute `{$name}` without any lints has no effect
+
+passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
+ .note = consider using `_{$name}` instead
+
+passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
+ .help = did you mean to capture by reference instead?
+
+passes_unused_var_remove_field = unused variable: `{$name}`
+passes_unused_var_remove_field_suggestion = try removing the field
+
+passes_unused_variable_try_ignore = unused variable: `{$name}`
+ .suggestion = try ignoring the field
passes_unused_variable_try_prefix = unused variable: `{$name}`
.label = unused variable
.suggestion = if this is intentional, prefix it with an underscore
-passes_unused_variable_try_ignore = unused variable: `{$name}`
- .suggestion = try ignoring the field
+passes_used_compiler_linker =
+ `used(compiler)` and `used(linker)` can't be used together
+
+passes_used_static =
+ attribute must be applied to a `static` variable
+
+passes_useless_assignment =
+ useless assignment of {$is_field_assign ->
+ [true] field
+ *[false] variable
+ } of type `{$ty}` to itself
+
+passes_useless_stability =
+ this stability annotation is useless
+ .label = useless stability annotation
+ .item = the stability attribute annotates this item
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 41f9222..c3189d1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1816,7 +1816,7 @@
|| (is_simd && is_c)
|| (int_reprs == 1
&& is_c
- && item.map_or(false, |item| {
+ && item.is_some_and(|item| {
if let ItemLike::Item(item) = item {
return is_c_like_enum(item);
}
@@ -2095,7 +2095,7 @@
| sym::feature
| sym::repr
| sym::target_feature
- ) && attr.meta_item_list().map_or(false, |list| list.is_empty())
+ ) && attr.meta_item_list().is_some_and(|list| list.is_empty())
{
errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
} else if matches!(
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index f906032..b81b7ad 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -554,10 +554,8 @@
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|| self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
- let is_stable = self
- .tcx
- .lookup_stability(def_id)
- .map_or(false, |stability| stability.level.is_stable());
+ let is_stable =
+ self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();
let is_reachable = self.effective_visibilities.is_reachable(def_id);
@@ -772,7 +770,7 @@
// needs to have an error emitted.
if features.const_trait_impl
&& *constness == hir::Constness::Const
- && const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
+ && const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
{
self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
}
@@ -809,15 +807,12 @@
);
let is_allowed_through_unstable_modules = |def_id| {
- self.tcx
- .lookup_stability(def_id)
- .map(|stab| match stab.level {
- StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
- allowed_through_unstable_modules
- }
- _ => false,
- })
- .unwrap_or(false)
+ self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level {
+ StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
+ allowed_through_unstable_modules
+ }
+ _ => false,
+ })
};
if item_is_allowed && !is_allowed_through_unstable_modules(def_id) {
diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl
index a26d1b2..b68e8a7 100644
--- a/compiler/rustc_privacy/messages.ftl
+++ b/compiler/rustc_privacy/messages.ftl
@@ -2,22 +2,22 @@
privacy_field_is_private_is_update_syntax_label = field `{$field_name}` is private
privacy_field_is_private_label = private field
-privacy_item_is_private = {$kind} `{$descr}` is private
- .label = private {$kind}
-privacy_unnamed_item_is_private = {$kind} is private
- .label = private {$kind}
+privacy_from_private_dep_in_public_interface =
+ {$kind} `{$descr}` from private dependency '{$krate}' in public interface
privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface
.label = can't leak {$vis_descr} {$kind}
.visibility_label = `{$descr}` declared as {$vis_descr}
-privacy_report_effective_visibility = {$descr}
-
-privacy_from_private_dep_in_public_interface =
- {$kind} `{$descr}` from private dependency '{$krate}' in public interface
-
+privacy_item_is_private = {$kind} `{$descr}` is private
+ .label = private {$kind}
privacy_private_in_public_lint =
{$vis_descr} {$kind} `{$descr}` in public interface (error {$kind ->
[trait] E0445
*[other] E0446
})
+
+privacy_report_effective_visibility = {$descr}
+
+privacy_unnamed_item_is_private = {$kind} is private
+ .label = private {$kind}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 7b39cb0..65dfdf3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -454,12 +454,14 @@
/// n::p::f()
/// }
macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
+ /// Preliminary pass for marking all underlying types of `impl Trait`s as reachable.
+ impl_trait_pass: bool,
/// Has something changed in the level map?
changed: bool,
}
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
- effective_vis: Option<EffectiveVisibility>,
+ effective_vis: EffectiveVisibility,
item_def_id: LocalDefId,
ev: &'a mut EmbargoVisitor<'tcx>,
level: Level,
@@ -474,7 +476,7 @@
fn update(
&mut self,
def_id: LocalDefId,
- inherited_effective_vis: Option<EffectiveVisibility>,
+ inherited_effective_vis: EffectiveVisibility,
level: Level,
) {
let nominal_vis = self.tcx.local_visibility(def_id);
@@ -484,30 +486,27 @@
fn update_eff_vis(
&mut self,
def_id: LocalDefId,
- inherited_effective_vis: Option<EffectiveVisibility>,
+ inherited_effective_vis: EffectiveVisibility,
nominal_vis: Option<ty::Visibility>,
level: Level,
) {
- if let Some(inherited_effective_vis) = inherited_effective_vis {
- let private_vis =
- ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
- if Some(private_vis) != nominal_vis {
- self.changed |= self.effective_visibilities.update(
- def_id,
- nominal_vis,
- || private_vis,
- inherited_effective_vis,
- level,
- self.tcx,
- );
- }
+ let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
+ if Some(private_vis) != nominal_vis {
+ self.changed |= self.effective_visibilities.update(
+ def_id,
+ nominal_vis,
+ || private_vis,
+ inherited_effective_vis,
+ level,
+ self.tcx,
+ );
}
}
fn reach(
&mut self,
def_id: LocalDefId,
- effective_vis: Option<EffectiveVisibility>,
+ effective_vis: EffectiveVisibility,
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
effective_vis,
@@ -520,7 +519,7 @@
fn reach_through_impl_trait(
&mut self,
def_id: LocalDefId,
- effective_vis: Option<EffectiveVisibility>,
+ effective_vis: EffectiveVisibility,
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
effective_vis,
@@ -532,9 +531,13 @@
// We have to make sure that the items that macros might reference
// are reachable, since they might be exported transitively.
- fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) {
+ fn update_reachability_from_macro(
+ &mut self,
+ local_def_id: LocalDefId,
+ md: &MacroDef,
+ macro_ev: EffectiveVisibility,
+ ) {
// Non-opaque macros cannot make other items more accessible than they already are.
-
let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
let attrs = self.tcx.hir().attrs(hir_id);
if attr::find_transparency(attrs, md.macro_rules).0 != Transparency::Opaque {
@@ -554,8 +557,6 @@
// Since we are starting from an externally visible module,
// all the parents in the loop below are also guaranteed to be modules.
let mut module_def_id = macro_module_def_id;
- let macro_ev = self.get(local_def_id);
- assert!(macro_ev.is_some());
loop {
let changed_reachability =
self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
@@ -572,7 +573,7 @@
&mut self,
module_def_id: LocalDefId,
defining_mod: LocalDefId,
- macro_ev: Option<EffectiveVisibility>,
+ macro_ev: EffectiveVisibility,
) -> bool {
if self.macro_reachable.insert((module_def_id, defining_mod)) {
self.update_macro_reachable_mod(module_def_id, defining_mod, macro_ev);
@@ -586,7 +587,7 @@
&mut self,
module_def_id: LocalDefId,
defining_mod: LocalDefId,
- macro_ev: Option<EffectiveVisibility>,
+ macro_ev: EffectiveVisibility,
) {
let module = self.tcx.hir().get_module(module_def_id).0;
for item_id in module.item_ids {
@@ -618,7 +619,7 @@
def_kind: DefKind,
vis: ty::Visibility,
module: LocalDefId,
- macro_ev: Option<EffectiveVisibility>,
+ macro_ev: EffectiveVisibility,
) {
self.update(def_id, macro_ev, Level::Reachable);
match def_kind {
@@ -700,128 +701,53 @@
}
impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
- type NestedFilter = nested_filter::All;
-
- /// We want to visit items in the context of their containing
- /// module and so forth, so supply a crate for doing a deep walk.
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let item_ev = match item.kind {
- hir::ItemKind::Impl { .. } => {
- let impl_ev = Option::<EffectiveVisibility>::of_impl(
- item.owner_id.def_id,
- self.tcx,
- &self.effective_visibilities,
- );
-
- self.update_eff_vis(item.owner_id.def_id, impl_ev, None, Level::Direct);
- impl_ev
- }
- _ => self.get(item.owner_id.def_id),
- };
-
- // Update levels of nested things.
- match item.kind {
- hir::ItemKind::Enum(ref def, _) => {
- for variant in def.variants {
- self.update(variant.def_id, item_ev, Level::Reachable);
- let variant_ev = self.get(variant.def_id);
- if let Some(ctor_def_id) = variant.data.ctor_def_id() {
- self.update(ctor_def_id, variant_ev, Level::Reachable);
- }
- for field in variant.data.fields() {
- self.update(field.def_id, variant_ev, Level::Reachable);
- }
- }
- }
- hir::ItemKind::Impl(ref impl_) => {
- for impl_item_ref in impl_.items {
- let def_id = impl_item_ref.id.owner_id.def_id;
- let nominal_vis =
- impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
- self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
- }
- }
- hir::ItemKind::Trait(.., trait_item_refs) => {
- for trait_item_ref in trait_item_refs {
- self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
- }
- }
- hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
- if let Some(ctor_def_id) = def.ctor_def_id() {
- self.update(ctor_def_id, item_ev, Level::Reachable);
- }
- for field in def.fields() {
- self.update(field.def_id, item_ev, Level::Reachable);
- }
- }
- hir::ItemKind::Macro(ref macro_def, _) => {
- self.update_reachability_from_macro(item.owner_id.def_id, macro_def);
- }
- hir::ItemKind::ForeignMod { items, .. } => {
- for foreign_item in items {
- self.update(foreign_item.id.owner_id.def_id, item_ev, Level::Reachable);
- }
- }
-
- hir::ItemKind::OpaqueTy(..)
- | hir::ItemKind::Use(..)
- | hir::ItemKind::Static(..)
- | hir::ItemKind::Const(..)
- | hir::ItemKind::GlobalAsm(..)
- | hir::ItemKind::TyAlias(..)
- | hir::ItemKind::Mod(..)
- | hir::ItemKind::TraitAlias(..)
- | hir::ItemKind::Fn(..)
- | hir::ItemKind::ExternCrate(..) => {}
+ if self.impl_trait_pass
+ && let hir::ItemKind::OpaqueTy(ref opaque) = item.kind
+ && !opaque.in_trait {
+ // FIXME: This is some serious pessimization intended to workaround deficiencies
+ // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
+ // reachable if they are returned via `impl Trait`, even from private functions.
+ let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
+ self.reach_through_impl_trait(item.owner_id.def_id, pub_ev)
+ .generics()
+ .predicates()
+ .ty();
+ return;
}
- // Mark all items in interfaces of reachable items as reachable.
+ // Update levels of nested things and mark all items
+ // in interfaces of reachable items as reachable.
+ let item_ev = self.get(item.owner_id.def_id);
match item.kind {
- // The interface is empty.
- hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
- // All nested items are checked by `visit_item`.
- hir::ItemKind::Mod(..) => {}
- // Handled in `rustc_resolve`.
- hir::ItemKind::Use(..) => {}
- // The interface is empty.
- hir::ItemKind::GlobalAsm(..) => {}
- hir::ItemKind::OpaqueTy(ref opaque) => {
- // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
- // Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
- // mark this as unreachable.
- // See https://github.com/rust-lang/rust/issues/75100
- if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc {
- // FIXME: This is some serious pessimization intended to workaround deficiencies
- // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
- // reachable if they are returned via `impl Trait`, even from private functions.
- let exist_ev = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
- self.reach_through_impl_trait(item.owner_id.def_id, exist_ev)
- .generics()
- .predicates()
- .ty();
+ // The interface is empty, and no nested items.
+ hir::ItemKind::Use(..)
+ | hir::ItemKind::ExternCrate(..)
+ | hir::ItemKind::GlobalAsm(..) => {}
+ // The interface is empty, and all nested items are processed by `visit_item`.
+ hir::ItemKind::Mod(..) | hir::ItemKind::OpaqueTy(..) => {}
+ hir::ItemKind::Macro(ref macro_def, _) => {
+ if let Some(item_ev) = item_ev {
+ self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev);
}
}
- // Visit everything.
hir::ItemKind::Const(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Fn(..)
| hir::ItemKind::TyAlias(..) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
for trait_item_ref in trait_item_refs {
+ self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
+
let tcx = self.tcx;
let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
-
reach.generics().predicates();
if trait_item_ref.kind == AssocItemKind::Type
@@ -835,13 +761,18 @@
}
}
hir::ItemKind::TraitAlias(..) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
}
}
- // Visit everything except for private impl items.
hir::ItemKind::Impl(ref impl_) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = Option::<EffectiveVisibility>::of_impl(
+ item.owner_id.def_id,
+ self.tcx,
+ &self.effective_visibilities,
+ ) {
+ self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
+
self.reach(item.owner_id.def_id, item_ev)
.generics()
.predicates()
@@ -849,27 +780,32 @@
.trait_ref();
for impl_item_ref in impl_.items {
- let impl_item_ev = self.get(impl_item_ref.id.owner_id.def_id);
+ let def_id = impl_item_ref.id.owner_id.def_id;
+ let nominal_vis =
+ impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
+ self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
- if impl_item_ev.is_some() {
- self.reach(impl_item_ref.id.owner_id.def_id, impl_item_ev)
- .generics()
- .predicates()
- .ty();
+ if let Some(impl_item_ev) = self.get(def_id) {
+ self.reach(def_id, impl_item_ev).generics().predicates().ty();
}
}
}
}
-
- // Visit everything, but enum variants have their own levels.
hir::ItemKind::Enum(ref def, _) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
}
for variant in def.variants {
- let variant_ev = self.get(variant.def_id);
- if variant_ev.is_some() {
+ if let Some(item_ev) = item_ev {
+ self.update(variant.def_id, item_ev, Level::Reachable);
+ }
+
+ if let Some(variant_ev) = self.get(variant.def_id) {
+ if let Some(ctor_def_id) = variant.data.ctor_def_id() {
+ self.update(ctor_def_id, variant_ev, Level::Reachable);
+ }
for field in variant.data.fields() {
+ self.update(field.def_id, variant_ev, Level::Reachable);
self.reach(field.def_id, variant_ev).ty();
}
// Corner case: if the variant is reachable, but its
@@ -877,18 +813,15 @@
self.reach(item.owner_id.def_id, variant_ev).ty();
}
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
- let ctor_ev = self.get(ctor_def_id);
- if ctor_ev.is_some() {
+ if let Some(ctor_ev) = self.get(ctor_def_id) {
self.reach(item.owner_id.def_id, ctor_ev).ty();
}
}
}
}
- // Visit everything, but foreign items have their own levels.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- let foreign_item_ev = self.get(foreign_item.id.owner_id.def_id);
- if foreign_item_ev.is_some() {
+ if let Some(foreign_item_ev) = self.get(foreign_item.id.owner_id.def_id) {
self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
.generics()
.predicates()
@@ -896,34 +829,26 @@
}
}
}
- // Visit everything except for private fields.
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
- if item_ev.is_some() {
+ if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
for field in struct_def.fields() {
- let field_ev = self.get(field.def_id);
- if field_ev.is_some() {
+ self.update(field.def_id, item_ev, Level::Reachable);
+ if let Some(field_ev) = self.get(field.def_id) {
self.reach(field.def_id, field_ev).ty();
}
}
}
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
- let ctor_ev = self.get(ctor_def_id);
- if ctor_ev.is_some() {
+ if let Some(item_ev) = item_ev {
+ self.update(ctor_def_id, item_ev, Level::Reachable);
+ }
+ if let Some(ctor_ev) = self.get(ctor_def_id) {
self.reach(item.owner_id.def_id, ctor_ev).ty();
}
}
}
}
-
- intravisit::walk_item(self, item);
- }
-
- fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) {
- // Blocks can have public items, for example impls, but they always
- // start as completely private regardless of publicity of a function,
- // constant, type, field, etc., in which this block resides.
- intravisit::walk_block(self, b);
}
}
@@ -2205,12 +2130,24 @@
tcx,
effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
macro_reachable: Default::default(),
+ // HACK(jynelson): trying to infer the type of `impl Trait` breaks `async-std` (and
+ // `pub async fn` in general). Since rustdoc never needs to do codegen and doesn't
+ // care about link-time reachability, keep them unreachable (issue #75100).
+ impl_trait_pass: !tcx.sess.opts.actually_rustdoc,
changed: false,
};
visitor.effective_visibilities.check_invariants(tcx, true);
+ if visitor.impl_trait_pass {
+ // Underlying types of `impl Trait`s are marked as reachable unconditionally,
+ // so this pass doesn't need to be a part of the fixed point iteration below.
+ tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
+ visitor.impl_trait_pass = false;
+ visitor.changed = false;
+ }
+
loop {
- tcx.hir().walk_toplevel_module(&mut visitor);
+ tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
if visitor.changed {
visitor.changed = false;
} else {
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 0d01123..49b423d 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,4 +1,20 @@
-query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
+query_system_cycle = cycle detected when {$stack_bottom}
+
+query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
+
+query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
+query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
+query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
+
+query_system_cycle_stack_middle = ...which requires {$desc}...
+
+query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
+
+query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
+
+query_system_cycle_usage = cycle used when {$usage}
+
+query_system_cycle_which_requires = ...which requires {$desc}...
query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
.help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
@@ -6,25 +22,9 @@
query_system_increment_compilation_note1 = Please follow the instructions below to create a bug report with the provided information
query_system_increment_compilation_note2 = See <https://github.com/rust-lang/rust/issues/84970> for more information
-query_system_cycle = cycle detected when {$stack_bottom}
-
-query_system_cycle_usage = cycle used when {$usage}
-
-query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
-
-query_system_cycle_stack_middle = ...which requires {$desc}...
-
-query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
-
-query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
-query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
-query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
-
-query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
-
-query_system_cycle_which_requires = ...which requires {$desc}...
+query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
query_system_query_overflow = queries overflow the depth limit!
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
+query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 8de4d06..c0d7386 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -656,7 +656,7 @@
/// current compilation session. Used in various assertions
#[inline]
pub fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool {
- self.colors.get(prev_index).map_or(false, |c| c.is_green())
+ self.colors.get(prev_index).is_some_and(|c| c.is_green())
}
#[inline]
@@ -677,7 +677,7 @@
impl<K: DepKind> DepGraph<K> {
#[inline]
pub fn dep_node_exists(&self, dep_node: &DepNode<K>) -> bool {
- self.data.as_ref().map_or(false, |data| data.dep_node_exists(dep_node))
+ self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node))
}
/// Checks whether a previous work product exists for `v` and, if
@@ -955,7 +955,7 @@
/// Returns true if the given node has been marked as green during the
/// current compilation session. Used in various assertions
pub fn is_green(&self, dep_node: &DepNode<K>) -> bool {
- self.node_color(dep_node).map_or(false, |c| c.is_green())
+ self.node_color(dep_node).is_some_and(|c| c.is_green())
}
/// This method loads all on-disk cacheable query results into memory, so
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 8865ecf..e673d5b 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -24,7 +24,7 @@
.iter()
.filter(|attr| {
!attr.is_doc_comment()
- && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
+ && !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name))
})
.collect();
@@ -38,7 +38,7 @@
impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
// Make sure that these have been filtered out.
- debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name)));
+ debug_assert!(!attr.ident().is_some_and(|ident| self.is_ignored_attr(ident.name)));
debug_assert!(!attr.is_doc_comment());
let ast::Attribute { kind, id: _, style, span } = attr;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 5f2ec65..f45f7ca 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -22,7 +22,7 @@
rustc_data_structures::fx::FxHashSet,
rustc_data_structures::sync::Lock,
rustc_data_structures::sync::Lrc,
- rustc_data_structures::{jobserver, OnDrop},
+ rustc_data_structures::{defer, jobserver},
rustc_span::DUMMY_SP,
std::iter,
std::process,
@@ -530,7 +530,7 @@
/// all active queries for cycles before finally resuming all the waiters at once.
#[cfg(parallel_compiler)]
pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
- let on_panic = OnDrop(|| {
+ let on_panic = defer(|| {
eprintln!("deadlock handler panicked, aborting process");
process::abort();
});
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 1c16d85..46da0aa 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -7,7 +7,7 @@
[dependencies]
bitflags = "1.2.1"
-pulldown-cmark = { version = "0.9.2", default-features = false }
+pulldown-cmark = { version = "0.9.3", default-features = false }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 345255c..539b88a 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -1,134 +1,38 @@
-resolve_parent_module_reset_for_binding =
- parent module is reset for binding
+resolve_accessible_unsure = not sure whether the path is accessible or not
+ .note = the type may have associated items, but we are currently not checking them
+
+resolve_add_as_non_derive =
+ add as non-Derive macro
+ `#[{$macro_path}]`
resolve_ampersand_used_without_explicit_lifetime_name =
`&` without an explicit lifetime name cannot be used here
.note = explicit lifetime name needed here
-resolve_underscore_lifetime_name_cannot_be_used_here =
- `'_` cannot be used here
- .note = `'_` is a reserved lifetime name
-
-resolve_crate_may_not_be_imported =
- `$crate` may not be imported
-
-resolve_crate_root_imports_must_be_named_explicitly =
- crate root imports need to be explicitly named: `use crate as name;`
-
-resolve_generic_params_from_outer_function =
- can't use generic parameters from outer function
- .label = use of generic parameter from outer function
- .suggestion = try using a local generic parameter instead
-
-resolve_self_type_implicitly_declared_by_impl =
- `Self` type implicitly declared here, by this `impl`
-
-resolve_cannot_use_self_type_here =
- can't use `Self` here
-
-resolve_use_a_type_here_instead =
- use a type here instead
-
-resolve_type_param_from_outer_fn =
- type parameter from outer function
-
-resolve_const_param_from_outer_fn =
- const parameter from outer function
-
-resolve_try_using_local_generic_parameter =
- try using a local generic parameter instead
-
-resolve_try_adding_local_generic_param_on_method =
- try adding a local generic parameter in this method instead
-
-resolve_help_try_using_local_generic_param =
- try using a local generic parameter instead
-
-resolve_name_is_already_used_as_generic_parameter =
- the name `{$name}` is already used for a generic parameter in this item's generic parameters
- .label = already used
- .first_use_of_name = first use of `{$name}`
-
-resolve_method_not_member_of_trait =
- method `{$method}` is not a member of trait `{$trait_}`
- .label = not a member of trait `{$trait_}`
-
-resolve_associated_fn_with_similar_name_exists =
- there is an associated function with a similar name
-
-resolve_type_not_member_of_trait =
- type `{$type_}` is not a member of trait `{$trait_}`
- .label = not a member of trait `{$trait_}`
-
-resolve_associated_type_with_similar_name_exists =
- there is an associated type with a similar name
-
-resolve_const_not_member_of_trait =
- const `{$const_}` is not a member of trait `{$trait_}`
- .label = not a member of trait `{$trait_}`
+resolve_ancestor_only =
+ visibilities can only be restricted to ancestor modules
resolve_associated_const_with_similar_name_exists =
there is an associated constant with a similar name
-resolve_variable_bound_with_different_mode =
- variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
- .label = bound in different ways
- .first_binding_span = first binding
+resolve_associated_fn_with_similar_name_exists =
+ there is an associated function with a similar name
-resolve_ident_bound_more_than_once_in_parameter_list =
- identifier `{$identifier}` is bound more than once in this parameter list
- .label = used as parameter more than once
-
-resolve_ident_bound_more_than_once_in_same_pattern =
- identifier `{$identifier}` is bound more than once in the same pattern
- .label = used in a pattern more than once
-
-resolve_undeclared_label =
- use of undeclared label `{$name}`
- .label = undeclared label `{$name}`
-
-resolve_label_with_similar_name_reachable =
- a label with a similar name is reachable
-
-resolve_try_using_similarly_named_label =
- try using similarly named label
-
-resolve_unreachable_label_with_similar_name_exists =
- a label with a similar name exists but is unreachable
-
-resolve_self_import_can_only_appear_once_in_the_list =
- `self` import can only appear once in an import list
- .label = can only appear once in an import list
-
-resolve_self_import_only_in_import_list_with_non_empty_prefix =
- `self` import can only appear in an import list with a non-empty prefix
- .label = can only appear in an import list with a non-empty prefix
-
-resolve_cannot_capture_dynamic_environment_in_fn_item =
- can't capture dynamic environment in a fn item
- .help = use the `|| {"{"} ... {"}"}` closure form instead
+resolve_associated_type_with_similar_name_exists =
+ there is an associated type with a similar name
resolve_attempt_to_use_non_constant_value_in_constant =
attempt to use a non-constant value in a constant
-resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
- consider using `{$suggestion}` instead of `{$current}`
-
resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion =
non-constant value
+resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
+ consider using `{$suggestion}` instead of `{$current}`
+
resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
this would need to be a `{$suggestion}`
-resolve_self_imports_only_allowed_within =
- `self` imports are only allowed within a {"{"} {"}"} list
-
-resolve_self_imports_only_allowed_within_suggestion =
- consider importing the module directly
-
-resolve_self_imports_only_allowed_within_multipart_suggestion =
- alternatively, use the multi-path `use` syntax to import `self`
-
resolve_binding_shadows_something_unacceptable =
{$shadowing_binding}s cannot shadow {$shadowed_binding}s
.label = cannot be named the same as {$article} {$shadowed_binding}
@@ -137,26 +41,105 @@
resolve_binding_shadows_something_unacceptable_suggestion =
try specify the pattern arguments
-resolve_forward_declared_generic_param =
- generic parameters with a default cannot use forward declared identifiers
- .label = defaulted generic parameters cannot be forward declared
+resolve_cannot_capture_dynamic_environment_in_fn_item =
+ can't capture dynamic environment in a fn item
+ .help = use the `|| {"{"} ... {"}"}` closure form instead
-resolve_param_in_ty_of_const_param =
- the type of const parameters must not depend on other generic parameters
- .label = the type must not depend on the parameter `{$name}`
+resolve_cannot_use_self_type_here =
+ can't use `Self` here
-resolve_type_param_in_ty_of_const_param =
- type parameters may not be used in the type of const parameters
+resolve_const_not_member_of_trait =
+ const `{$const_}` is not a member of trait `{$trait_}`
+ .label = not a member of trait `{$trait_}`
+
+resolve_const_param_from_outer_fn =
+ const parameter from outer function
+
+resolve_const_param_in_enum_discriminant =
+ const parameters may not be used in enum discriminant values
+
+resolve_const_param_in_non_trivial_anon_const =
+ const parameters may only be used as standalone arguments, i.e. `{$name}`
resolve_const_param_in_ty_of_const_param =
const parameters may not be used in the type of const parameters
+resolve_crate_may_not_be_imported =
+ `$crate` may not be imported
+
+resolve_crate_root_imports_must_be_named_explicitly =
+ crate root imports need to be explicitly named: `use crate as name;`
+
+resolve_expected_found =
+ expected module, found {$res} `{$path_str}`
+ .label = not a module
+
+resolve_forward_declared_generic_param =
+ generic parameters with a default cannot use forward declared identifiers
+ .label = defaulted generic parameters cannot be forward declared
+
+resolve_generic_params_from_outer_function =
+ can't use generic parameters from outer function
+ .label = use of generic parameter from outer function
+ .suggestion = try using a local generic parameter instead
+
+resolve_help_try_using_local_generic_param =
+ try using a local generic parameter instead
+
+resolve_ident_bound_more_than_once_in_parameter_list =
+ identifier `{$identifier}` is bound more than once in this parameter list
+ .label = used as parameter more than once
+
+resolve_ident_bound_more_than_once_in_same_pattern =
+ identifier `{$identifier}` is bound more than once in the same pattern
+ .label = used in a pattern more than once
+
+resolve_imported_crate = `$crate` may not be imported
+
+resolve_indeterminate =
+ cannot determine resolution for the visibility
+
+resolve_invalid_asm_sym =
+ invalid `sym` operand
+ .label = is a local variable
+ .help = `sym` operands must refer to either a function or a static
+
+resolve_label_with_similar_name_reachable =
+ a label with a similar name is reachable
+
+resolve_lifetime_param_in_enum_discriminant =
+ lifetime parameters may not be used in enum discriminant values
+
+resolve_lifetime_param_in_non_trivial_anon_const =
+ lifetime parameters may not be used in const expressions
+
resolve_lifetime_param_in_ty_of_const_param =
lifetime parameters may not be used in the type of const parameters
-resolve_self_in_generic_param_default =
- generic parameters cannot use `Self` in their defaults
- .label = `Self` in generic parameter default
+resolve_lowercase_self =
+ attempt to use a non-constant value in a constant
+ .suggestion = try using `Self`
+
+resolve_macro_expected_found =
+ expected {$expected}, found {$found} `{$macro_path}`
+
+resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
+
+resolve_method_not_member_of_trait =
+ method `{$method}` is not a member of trait `{$trait_}`
+ .label = not a member of trait `{$trait_}`
+
+resolve_module_only =
+ visibility must resolve to a module
+
+resolve_name_is_already_used_as_generic_parameter =
+ the name `{$name}` is already used for a generic parameter in this item's generic parameters
+ .label = already used
+ .first_use_of_name = first use of `{$name}`
+
+resolve_param_in_enum_discriminant =
+ generic parameters may not be used in enum discriminant values
+ .label = cannot perform const operation using `{$name}`
resolve_param_in_non_trivial_anon_const =
generic parameters may not be used in const operations
@@ -165,43 +148,50 @@
resolve_param_in_non_trivial_anon_const_help =
use `#![feature(generic_const_exprs)]` to allow generic const expressions
-resolve_type_param_in_non_trivial_anon_const =
- type parameters may not be used in const expressions
+resolve_param_in_ty_of_const_param =
+ the type of const parameters must not depend on other generic parameters
+ .label = the type must not depend on the parameter `{$name}`
-resolve_const_param_in_non_trivial_anon_const =
- const parameters may only be used as standalone arguments, i.e. `{$name}`
+resolve_parent_module_reset_for_binding =
+ parent module is reset for binding
-resolve_lifetime_param_in_non_trivial_anon_const =
- lifetime parameters may not be used in const expressions
+resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
+ .help = you can define integration tests in a directory named `tests`
-resolve_unreachable_label =
- use of unreachable label `{$name}`
- .label = unreachable label `{$name}`
- .label_definition_span = unreachable label defined here
- .note = labels are unreachable through functions, closures, async blocks and modules
+resolve_relative_2018 =
+ relative paths are not supported in visibilities in 2018 edition or later
+ .suggestion = try
-resolve_unreachable_label_suggestion_use_similarly_named =
- try using similarly named label
+resolve_remove_surrounding_derive =
+ remove from the surrounding `derive()`
-resolve_unreachable_label_similar_name_reachable =
- a label with a similar name is reachable
+resolve_self_import_can_only_appear_once_in_the_list =
+ `self` import can only appear once in an import list
+ .label = can only appear once in an import list
-resolve_unreachable_label_similar_name_unreachable =
- a label with a similar name exists but is also unreachable
+resolve_self_import_only_in_import_list_with_non_empty_prefix =
+ `self` import can only appear in an import list with a non-empty prefix
+ .label = can only appear in an import list with a non-empty prefix
-resolve_trait_impl_mismatch =
- item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
- .label = does not match trait
- .label_trait_item = item in trait
+resolve_self_imports_only_allowed_within =
+ `self` imports are only allowed within a {"{"} {"}"} list
-resolve_invalid_asm_sym =
- invalid `sym` operand
- .label = is a local variable
- .help = `sym` operands must refer to either a function or a static
+resolve_self_imports_only_allowed_within_multipart_suggestion =
+ alternatively, use the multi-path `use` syntax to import `self`
-resolve_lowercase_self =
- attempt to use a non-constant value in a constant
- .suggestion = try using `Self`
+resolve_self_imports_only_allowed_within_suggestion =
+ consider importing the module directly
+
+resolve_self_in_generic_param_default =
+ generic parameters cannot use `Self` in their defaults
+ .label = `Self` in generic parameter default
+
+resolve_self_type_implicitly_declared_by_impl =
+ `Self` type implicitly declared here, by this `impl`
+
+resolve_tool_module_imported =
+ cannot use a tool module through an import
+ .note = the tool module imported here
resolve_trait_impl_duplicate =
duplicate definitions with name `{$name}`:
@@ -209,56 +199,66 @@
.old_span_label = previous definition here
.trait_item_span = item in trait
-resolve_relative_2018 =
- relative paths are not supported in visibilities in 2018 edition or later
- .suggestion = try
+resolve_trait_impl_mismatch =
+ item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
+ .label = does not match trait
+ .label_trait_item = item in trait
-resolve_ancestor_only =
- visibilities can only be restricted to ancestor modules
+resolve_try_adding_local_generic_param_on_method =
+ try adding a local generic parameter in this method instead
-resolve_expected_found =
- expected module, found {$res} `{$path_str}`
- .label = not a module
+resolve_try_using_local_generic_parameter =
+ try using a local generic parameter instead
-resolve_indeterminate =
- cannot determine resolution for the visibility
+resolve_try_using_similarly_named_label =
+ try using similarly named label
-resolve_tool_module_imported =
- cannot use a tool module through an import
- .note = the tool module imported here
+resolve_type_not_member_of_trait =
+ type `{$type_}` is not a member of trait `{$trait_}`
+ .label = not a member of trait `{$trait_}`
-resolve_module_only =
- visibility must resolve to a module
-
-resolve_macro_expected_found =
- expected {$expected}, found {$found} `{$macro_path}`
-
-resolve_remove_surrounding_derive =
- remove from the surrounding `derive()`
-
-resolve_add_as_non_derive =
- add as non-Derive macro
- `#[{$macro_path}]`
-
-resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
- .help = you can define integration tests in a directory named `tests`
-
-resolve_imported_crate = `$crate` may not be imported
-
-resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
-
-resolve_accessible_unsure = not sure whether the path is accessible or not
- .note = the type may have associated items, but we are currently not checking them
-
-resolve_param_in_enum_discriminant =
- generic parameters may not be used in enum discriminant values
- .label = cannot perform const operation using `{$name}`
+resolve_type_param_from_outer_fn =
+ type parameter from outer function
resolve_type_param_in_enum_discriminant =
type parameters may not be used in enum discriminant values
-resolve_const_param_in_enum_discriminant =
- const parameters may not be used in enum discriminant values
+resolve_type_param_in_non_trivial_anon_const =
+ type parameters may not be used in const expressions
-resolve_lifetime_param_in_enum_discriminant =
- lifetime parameters may not be used in enum discriminant values
+resolve_type_param_in_ty_of_const_param =
+ type parameters may not be used in the type of const parameters
+
+resolve_undeclared_label =
+ use of undeclared label `{$name}`
+ .label = undeclared label `{$name}`
+
+resolve_underscore_lifetime_name_cannot_be_used_here =
+ `'_` cannot be used here
+ .note = `'_` is a reserved lifetime name
+
+resolve_unreachable_label =
+ use of unreachable label `{$name}`
+ .label = unreachable label `{$name}`
+ .label_definition_span = unreachable label defined here
+ .note = labels are unreachable through functions, closures, async blocks and modules
+
+resolve_unreachable_label_similar_name_reachable =
+ a label with a similar name is reachable
+
+resolve_unreachable_label_similar_name_unreachable =
+ a label with a similar name exists but is also unreachable
+
+resolve_unreachable_label_suggestion_use_similarly_named =
+ try using similarly named label
+
+resolve_unreachable_label_with_similar_name_exists =
+ a label with a similar name exists but is unreachable
+
+resolve_use_a_type_here_instead =
+ use a type here instead
+
+resolve_variable_bound_with_different_mode =
+ variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
+ .label = bound in different ways
+ .first_binding_span = first binding
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index b3d0e4b..7277773 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -129,7 +129,7 @@
expn_id,
self.def_span(def_id),
// FIXME: Account for `#[no_implicit_prelude]` attributes.
- parent.map_or(false, |module| module.no_implicit_prelude),
+ parent.is_some_and(|module| module.no_implicit_prelude),
));
}
}
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 17c4a6b..dc35c8b 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -117,16 +117,11 @@
match item.kind {
ast::UseTreeKind::Simple(Some(ident)) => {
if ident.name == kw::Underscore
- && !self
- .r
- .import_res_map
- .get(&id)
- .map(|per_ns| {
- per_ns.iter().filter_map(|res| res.as_ref()).any(|res| {
- matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
- })
+ && !self.r.import_res_map.get(&id).is_some_and(|per_ns| {
+ per_ns.iter().filter_map(|res| res.as_ref()).any(|res| {
+ matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
})
- .unwrap_or(false)
+ })
{
self.unused_import(self.base_id).add(id);
}
@@ -469,7 +464,7 @@
.r
.extern_prelude
.get(&extern_crate.ident)
- .map_or(false, |entry| !entry.introduced_by_item)
+ .is_some_and(|entry| !entry.introduced_by_item)
{
continue;
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index ed0a792..8c6ac82 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1843,7 +1843,7 @@
None,
)
}
- } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) {
+ } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
// Check whether the name refers to an item in the value namespace.
let binding = if let Some(ribs) = ribs {
self.resolve_ident_in_lexical_scope(
@@ -2165,7 +2165,7 @@
let is_definitely_crate = import
.module_path
.first()
- .map_or(false, |f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
+ .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
// Add the import to the start, with a `{` if required.
let start_point = source_map.start_point(after_crate_name);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c9131d8..df65825 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -197,8 +197,7 @@
.sess
.source_map()
.span_to_snippet(span)
- .map(|snippet| snippet.ends_with(')'))
- .unwrap_or(false)
+ .is_ok_and(|snippet| snippet.ends_with(')'))
}
Res::Def(
DefKind::Ctor(..) | DefKind::AssocFn | DefKind::Const | DefKind::AssocConst,
@@ -722,7 +721,7 @@
if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
&& res
.opt_def_id()
- .map_or(false, |id| id.is_local() || is_in_same_file(span, sugg_span))
+ .is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
{
err.span_label(
sugg_span,
@@ -856,7 +855,7 @@
// The current function has a `self` parameter, but we were unable to resolve
// a reference to `self`. This can only happen if the `self` identifier we
// are resolving came from a different hygiene context.
- if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
+ if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
} else {
let doesnt = if is_assoc_fn {
@@ -1632,7 +1631,7 @@
.tcx
.fn_arg_names(def_id)
.first()
- .map_or(false, |ident| ident.name == kw::SelfLower),
+ .is_some_and(|ident| ident.name == kw::SelfLower),
};
if has_self {
return Some(AssocSuggestion::MethodWithSelf { called });
@@ -1931,10 +1930,9 @@
let def_id = self.r.tcx.parent(ctor_def_id);
match kind {
CtorKind::Const => false,
- CtorKind::Fn => !self
- .r
- .field_def_ids(def_id)
- .map_or(false, |field_ids| field_ids.is_empty()),
+ CtorKind::Fn => {
+ !self.r.field_def_ids(def_id).is_some_and(|field_ids| field_ids.is_empty())
+ }
}
};
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 1e31a0f..3d2bd84 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1477,7 +1477,7 @@
}
fn is_builtin_macro(&mut self, res: Res) -> bool {
- self.get_macro(res).map_or(false, |macro_data| macro_data.ext.builtin_name.is_some())
+ self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
}
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 4da43c6..df5c16a 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -823,8 +823,7 @@
let is_allowed = |feature| {
self.active_features.contains(&feature) || span.allows_unstable(feature)
};
- let allowed_by_implication =
- implied_by.map(|feature| is_allowed(feature)).unwrap_or(false);
+ let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer;
let soft_handler =
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index a8fe560..5a0b8f9 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -1,13 +1,20 @@
-session_incorrect_cgu_reuse_type =
- CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
- [one] {"at least "}
- *[other] {""}
- }`{$expected_reuse}`
+session_binary_float_literal_not_supported = binary float literal is not supported
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
+session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+
+session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
session_cgu_not_recorded =
CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
-session_feature_gate_error = {$explain}
+session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+
+session_crate_name_empty = crate name must not be empty
+
+session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+
+session_expr_parentheses_needed = parentheses are required to parse this as an expression
session_feature_diagnostic_for_issue =
see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
@@ -15,66 +22,33 @@
session_feature_diagnostic_help =
add `#![feature({$feature})]` to the crate attributes to enable
-session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-
-session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
-
-session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
-
-session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
-
-session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
-
-session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
-
-session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
-
-session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
-
-session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
-
-session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
-
-session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
-
-session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
-
-session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
-
-session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
-
-session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
-
-session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
-
-session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
-
-session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
-
-session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
-
-session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+session_feature_gate_error = {$explain}
session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
-session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+session_incorrect_cgu_reuse_type =
+ CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
+ [one] {"at least "}
+ *[other] {""}
+ }`{$expected_reuse}`
-session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
-session_crate_name_empty = crate name must not be empty
+session_int_literal_too_large = integer literal is too large
+ .note = value exceeds limit of `{$limit}`
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
-session_expr_parentheses_needed = parentheses are required to parse this as an expression
+session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+ .label = invalid suffix `{$suffix}`
+ .help = valid suffixes are `f32` and `f64`
-session_skipping_const_checks = skipping const checks
-session_unleashed_feature_help_named = skipping check for `{$gate}` feature
-session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+session_invalid_float_literal_width = invalid width `{$width}` for float literal
+ .help = valid widths are 32 and 64
-session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-session_octal_float_literal_not_supported = octal float literal is not supported
-session_binary_float_literal_not_supported = binary float literal is not supported
-session_not_supported = not supported
+session_invalid_int_literal_width = invalid width `{$width}` for integer literal
+ .help = valid widths are 8, 16, 32, 64 and 128
session_invalid_literal_suffix = suffixes on {$kind} literals are invalid
.label = invalid suffix `{$suffix}`
@@ -87,19 +61,45 @@
.label = invalid suffix `{$suffix}`
.help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-session_invalid_float_literal_width = invalid width `{$width}` for float literal
- .help = valid widths are 32 and 64
+session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
-session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
- .label = invalid suffix `{$suffix}`
- .help = valid suffixes are `f32` and `f64`
+session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-session_int_literal_too_large = integer literal is too large
- .note = value exceeds limit of `{$limit}`
-
-session_invalid_int_literal_width = invalid width `{$width}` for integer literal
- .help = valid widths are 8, 16, 32, 64 and 128
-
-session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
+session_not_supported = not supported
session_nul_in_c_str = null characters in C string literals are not supported
+
+session_octal_float_literal_not_supported = octal float literal is not supported
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
+
+session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
+
+session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
+
+session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
+
+session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+
+session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+
+session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+
+session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
+
+session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
+
+session_skipping_const_checks = skipping const checks
+session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+
+session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+
+session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+
+session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+
+session_unleashed_feature_help_named = skipping check for `{$gate}` feature
+session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+
+session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
+
+session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index a328447..6c8c8e4 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1907,7 +1907,7 @@
error_format: ErrorOutputType,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
- if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
+ if cg.target_cpu.as_ref().is_some_and(|s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
cg.target_cpu = None;
};
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4f59308..bbe52db 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1378,8 +1378,8 @@
.lint_opts
.iter()
.rfind(|&(key, _)| *key == "warnings")
- .map_or(false, |&(_, level)| level == lint::Allow);
- let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
+ .is_some_and(|&(_, level)| level == lint::Allow);
+ let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
let sysroot = match &sopts.maybe_sysroot {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 6af43f5..5572108 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -309,7 +309,7 @@
Terminate => Terminator::Abort,
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
- Drop { place, target, unwind } => Terminator::Drop {
+ Drop { place, target, unwind, replace: _ } => Terminator::Drop {
place: rustc_place_to_place(place),
target: target.as_usize(),
unwind: rustc_unwind_to_unwind(unwind),
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index c669b64..b219fde 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -320,7 +320,6 @@
// Stop going up the backtrace once include! is encountered
if expn_data.is_root()
|| expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
- || expn_data.kind == ExpnKind::Inlined
{
break;
}
@@ -1058,8 +1057,6 @@
AstPass(AstPass),
/// Desugaring done by the compiler during HIR lowering.
Desugaring(DesugaringKind),
- /// MIR inlining
- Inlined,
}
impl ExpnKind {
@@ -1073,7 +1070,6 @@
},
ExpnKind::AstPass(kind) => kind.descr().to_string(),
ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()),
- ExpnKind::Inlined => "inlined source".to_string(),
}
}
}
@@ -1151,7 +1147,6 @@
Await,
ForLoop,
WhileLoop,
- Replace,
}
impl DesugaringKind {
@@ -1167,7 +1162,6 @@
DesugaringKind::OpaqueTy => "`impl Trait`",
DesugaringKind::ForLoop => "`for` loop",
DesugaringKind::WhileLoop => "`while` loop",
- DesugaringKind::Replace => "drop and replace",
}
}
}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 8d70aa4..eae3f0f 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -594,12 +594,6 @@
matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo
}
- /// Returns `true` if this span comes from MIR inlining.
- pub fn is_inlined(self) -> bool {
- let outer_expn = self.ctxt().outer_expn_data();
- matches!(outer_expn.kind, ExpnKind::Inlined)
- }
-
/// Returns `true` if `span` originates in a derive-macro's expansion.
pub fn in_derive_expansion(self) -> bool {
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
@@ -754,7 +748,7 @@
self.ctxt()
.outer_expn_data()
.allow_internal_unstable
- .map_or(false, |features| features.iter().any(|&f| f == feature))
+ .is_some_and(|features| features.iter().any(|&f| f == feature))
}
/// Checks if this span arises from a compiler desugaring of kind `kind`.
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 11ea5fe..1824510 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -639,7 +639,7 @@
self.span_to_source(sp, |src, start_index, end_index| {
Ok(src.get(start_index..end_index).is_some())
})
- .map_or(false, |is_accessible| is_accessible)
+ .is_ok_and(|is_accessible| is_accessible)
}
/// Returns the source snippet as `String` corresponding to the given `Span`.
@@ -835,7 +835,7 @@
}
return Ok(true);
})
- .map_or(false, |is_accessible| is_accessible)
+ .is_ok_and(|is_accessible| is_accessible)
}
/// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
@@ -967,7 +967,7 @@
for _ in 0..limit.unwrap_or(100_usize) {
sp = self.next_point(sp);
if let Ok(ref snippet) = self.span_to_snippet(sp) {
- if expect.map_or(false, |es| snippet == es) {
+ if expect.is_some_and(|es| snippet == es) {
break;
}
if expect.is_none() && snippet.chars().any(|c| !c.is_whitespace()) {
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index da8a16d..9fa4912 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -818,7 +818,7 @@
let field = variant.fields.iter().find(|field| {
let ty = tcx.type_of(field.did).subst_identity();
let is_zst =
- tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
+ tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_zst());
!is_zst
});
if let Some(field) = field {
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index b69ade7..9ac7323 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -4,7 +4,7 @@
pub fn target() -> Target {
let arch = Arch::Arm64;
let mut base = opts("macos", arch);
- base.cpu = "apple-a14".into();
+ base.cpu = "apple-m1".into();
base.max_atomic_width = Some(128);
// FIXME: The leak sanitizer currently fails the tests, see #88132.
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 2b135b6..e2df7e0 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "arm64-apple-ios-macabi";
+ let llvm_target = "arm64-apple-ios14.0-macabi";
let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
index d0c950c..523eb6b 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -1,10 +1,15 @@
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.max_atomic_width = Some(128);
base.supports_xray = true;
base.features = "+v8a".into();
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD;
Target {
llvm_target: "aarch64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index 5a3e2a7..9f3b0fa 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "x86_64-apple-ios-macabi";
+ let llvm_target = "x86_64-apple-ios14.0-macabi";
let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 8fea3fc..217ba71 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -1,17 +1,13 @@
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
-trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
-
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
.label = empty on-clause here
+trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+
trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
.label = invalid on-clause here
-trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
- .label = expected value here
- .note = eg `#[rustc_on_unimplemented(message="foo")]`
-
trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
[none] {""}
*[default] {" "}for type `{$self_desc}`
@@ -21,4 +17,8 @@
.positive_implementation_here = positive implementation here
.positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
-trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+ .label = expected value here
+ .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 142c200..312bd38 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -5,7 +5,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
-use rustc_middle::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, ToPredicate};
use rustc_span::DUMMY_SP;
@@ -82,8 +82,8 @@
fn enter_canonical_trait_query<K, R>(
&mut self,
canonical_key: &Canonical<'tcx, K>,
- operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+ operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+ ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
where
K: TypeFoldable<TyCtxt<'tcx>>,
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -110,8 +110,8 @@
fn enter_canonical_trait_query<K, R>(
&mut self,
canonical_key: &Canonical<'tcx, K>,
- operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+ operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+ ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
where
K: TypeFoldable<TyCtxt<'tcx>>,
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index d14e624..f32ff04 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -2,7 +2,6 @@
use super::search_graph::OverflowHandler;
use super::{EvalCtxt, SolverMode};
-use crate::solve::CanonicalResponseExt;
use crate::traits::coherence;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::DefId;
@@ -333,8 +332,7 @@
candidates: &mut Vec<Candidate<'tcx>>,
) {
let tcx = self.tcx();
- // FIXME: We also have to normalize opaque types, not sure where to best fit that in.
- let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
+ let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
return
};
@@ -356,8 +354,11 @@
}),
);
ecx.add_goal(normalizes_to_goal);
- let _ = ecx.try_evaluate_added_goals()?;
+ let _ = ecx.try_evaluate_added_goals().inspect_err(|_| {
+ debug!("self type normalization failed");
+ })?;
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
+ debug!(?normalized_ty, "self type normalized");
// NOTE: Alternatively we could call `evaluate_goal` here and only
// have a `Normalized` candidate. This doesn't work as long as we
// use `CandidateSource` in winnowing.
@@ -742,13 +743,18 @@
SolverMode::Normal => {
let param_env_responses = candidates
.iter()
- .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+ .filter(|c| {
+ matches!(
+ c.source,
+ CandidateSource::ParamEnv(_) | CandidateSource::AliasBound
+ )
+ })
.map(|c| c.result)
.collect::<Vec<_>>();
if let Some(result) = self.try_merge_responses(¶m_env_responses) {
- if result.has_only_region_constraints() {
- return Ok(result);
- }
+ // We strongly prefer alias and param-env bounds here, even if they affect inference.
+ // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11.
+ return Ok(result);
}
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 63a73f8..f91c672 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -1,4 +1,4 @@
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -9,7 +9,11 @@
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+use rustc_middle::traits::solve::{
+ CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
+ PredefinedOpaquesData, QueryResult,
+};
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor,
@@ -44,6 +48,9 @@
infcx: &'a InferCtxt<'tcx>,
pub(super) var_values: CanonicalVarValues<'tcx>,
+
+ predefined_opaques_in_body: PredefinedOpaques<'tcx>,
+
/// The highest universe index nameable by the caller.
///
/// When we enter a new binder inside of the query we create new universes
@@ -126,6 +133,11 @@
let mut ecx = EvalCtxt {
search_graph: &mut search_graph,
infcx: self,
+ // Only relevant when canonicalizing the response,
+ // which we don't do within this evaluation context.
+ predefined_opaques_in_body: self
+ .tcx
+ .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()),
// Only relevant when canonicalizing the response.
max_input_universe: ty::UniverseIndex::ROOT,
var_values: CanonicalVarValues::dummy(),
@@ -162,29 +174,53 @@
fn evaluate_canonical_goal(
tcx: TyCtxt<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
- canonical_goal: CanonicalGoal<'tcx>,
+ canonical_input: CanonicalInput<'tcx>,
) -> QueryResult<'tcx> {
// Deal with overflow, caching, and coinduction.
//
// The actual solver logic happens in `ecx.compute_goal`.
- search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
+ search_graph.with_new_goal(tcx, canonical_input, |search_graph| {
let intercrate = match search_graph.solver_mode() {
SolverMode::Normal => false,
SolverMode::Coherence => true,
};
- let (ref infcx, goal, var_values) = tcx
+ let (ref infcx, input, var_values) = tcx
.infer_ctxt()
.intercrate(intercrate)
- .build_with_canonical(DUMMY_SP, &canonical_goal);
+ .with_opaque_type_inference(canonical_input.value.anchor)
+ .build_with_canonical(DUMMY_SP, &canonical_input);
+
+ for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
+ let InferOk { value: (), obligations } = infcx
+ .register_hidden_type_in_new_solver(a, input.goal.param_env, b)
+ .expect("expected opaque type instantiation to succeed");
+ // We're only registering opaques already defined by the caller,
+ // so we're not responsible for proving that they satisfy their
+ // item bounds, unless we use them in a normalizes-to goal,
+ // which is handled in `EvalCtxt::unify_existing_opaque_tys`.
+ let _ = obligations;
+ }
let mut ecx = EvalCtxt {
infcx,
var_values,
- max_input_universe: canonical_goal.max_universe,
+ predefined_opaques_in_body: input.predefined_opaques_in_body,
+ max_input_universe: canonical_input.max_universe,
search_graph,
nested_goals: NestedGoals::new(),
tainted: Ok(()),
};
- ecx.compute_goal(goal)
+
+ let result = ecx.compute_goal(input.goal);
+
+ // When creating a query response we clone the opaque type constraints
+ // instead of taking them. This would cause an ICE here, since we have
+ // assertions against dropping an `InferCtxt` without taking opaques.
+ // FIXME: Once we remove support for the old impl we can remove this.
+ if input.anchor != DefiningAnchor::Error {
+ let _ = infcx.take_opaque_types();
+ }
+
+ result
})
}
@@ -199,7 +235,8 @@
let canonical_response =
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
- let has_changed = !canonical_response.value.var_values.is_identity();
+ let has_changed = !canonical_response.value.var_values.is_identity()
+ || !canonical_response.value.external_constraints.opaque_types.is_empty();
let (certainty, nested_goals) = self.instantiate_and_apply_query_response(
goal.param_env,
orig_values,
@@ -418,6 +455,7 @@
let mut ecx = EvalCtxt {
infcx: self.infcx,
var_values: self.var_values,
+ predefined_opaques_in_body: self.predefined_opaques_in_body,
max_input_universe: self.max_input_universe,
search_graph: self.search_graph,
nested_goals: self.nested_goals.clone(),
@@ -682,4 +720,56 @@
| rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
}
}
+
+ pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool {
+ self.infcx.opaque_type_origin(def_id).is_some()
+ }
+
+ pub(super) fn register_opaque_ty(
+ &mut self,
+ a: ty::OpaqueTypeKey<'tcx>,
+ b: Ty<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Result<(), NoSolution> {
+ let InferOk { value: (), obligations } =
+ self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
+ self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
+ Ok(())
+ }
+
+ // Do something for each opaque/hidden pair defined with `def_id` in the
+ // current inference context.
+ pub(super) fn unify_existing_opaque_tys(
+ &mut self,
+ param_env: ty::ParamEnv<'tcx>,
+ key: ty::OpaqueTypeKey<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Vec<CanonicalResponse<'tcx>> {
+ // FIXME: Super inefficient to be cloning this...
+ let opaques = self.infcx.clone_opaque_types_for_query_response();
+
+ let mut values = vec![];
+ for (candidate_key, candidate_ty) in opaques {
+ if candidate_key.def_id != key.def_id {
+ continue;
+ }
+ values.extend(self.probe(|ecx| {
+ for (a, b) in std::iter::zip(candidate_key.substs, key.substs) {
+ ecx.eq(param_env, a, b)?;
+ }
+ ecx.eq(param_env, candidate_ty, ty)?;
+ let mut obl = vec![];
+ ecx.infcx.add_item_bounds_for_hidden_type(
+ candidate_key,
+ ObligationCause::dummy(),
+ param_env,
+ candidate_ty,
+ &mut obl,
+ );
+ ecx.add_goals(obl.into_iter().map(Into::into));
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }));
+ }
+ values
+ }
}
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 67ad7fb..fdb209f 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -8,16 +8,19 @@
/// section of the [rustc-dev-guide][c].
///
/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
-use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
+use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
use crate::solve::{CanonicalResponse, QueryResult, Response};
use rustc_index::IndexVec;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
+use rustc_infer::infer::InferOk;
use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData, MaybeCause};
-use rustc_middle::ty::{self, BoundVar, GenericArgKind};
+use rustc_middle::traits::solve::{
+ ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
+};
+use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty};
use rustc_span::DUMMY_SP;
use std::iter;
use std::ops::Deref;
@@ -28,13 +31,21 @@
pub(super) fn canonicalize_goal(
&self,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
- ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
+ ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx>) {
let mut orig_values = Default::default();
let canonical_goal = Canonicalizer::canonicalize(
self.infcx,
CanonicalizeMode::Input,
&mut orig_values,
- goal,
+ QueryInput {
+ goal,
+ anchor: self.infcx.defining_use_anchor,
+ predefined_opaques_in_body: self.tcx().mk_predefined_opaques_in_body(
+ PredefinedOpaquesData {
+ opaque_types: self.infcx.clone_opaque_types_for_query_response(),
+ },
+ ),
+ },
);
(orig_values, canonical_goal)
}
@@ -138,7 +149,13 @@
region_constraints,
)
});
- let opaque_types = self.infcx.clone_opaque_types_for_query_response();
+
+ let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
+ // Only return opaque type keys for newly-defined opaques
+ opaque_types.retain(|(a, _)| {
+ self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
+ });
+
Ok(self
.tcx()
.mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
@@ -164,10 +181,10 @@
let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?;
- // FIXME: implement external constraints.
- let ExternalConstraintsData { region_constraints, opaque_types: _ } =
+ let ExternalConstraintsData { region_constraints, opaque_types } =
external_constraints.deref();
self.register_region_constraints(region_constraints);
+ self.register_opaque_types(param_env, opaque_types)?;
Ok((certainty, nested_goals))
}
@@ -287,4 +304,19 @@
let _ = member_constraint;
}
}
+
+ fn register_opaque_types(
+ &mut self,
+ param_env: ty::ParamEnv<'tcx>,
+ opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
+ ) -> Result<(), NoSolution> {
+ for &(a, b) in opaque_types {
+ let InferOk { value: (), obligations } =
+ self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
+ // It's sound to drop these obligations, since the normalizes-to goal
+ // is responsible for proving these obligations.
+ let _ = obligations;
+ }
+ Ok(())
+ }
}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 32bd10f..4a40319 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -133,12 +133,14 @@
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::ConstEvaluatable(_)
- | ty::PredicateKind::TypeWellFormedFromEnv(_)
| ty::PredicateKind::Ambiguous => {
FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,
)
}
+ ty::PredicateKind::TypeWellFormedFromEnv(_) => {
+ bug!("unexpected goal: {goal:?}")
+ }
},
root_obligation: obligation,
});
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index d94679f..56a254d 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -24,6 +24,7 @@
mod canonicalize;
mod eval_ctxt;
mod fulfill;
+mod opaques;
mod project_goals;
mod search_graph;
mod trait_goals;
@@ -212,7 +213,7 @@
);
}
- match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
+ match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS
@@ -230,44 +231,60 @@
let mut candidates = Vec::new();
// LHS normalizes-to RHS
- candidates.extend(
- evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No).ok(),
- );
+ candidates.extend(evaluate_normalizes_to(
+ self,
+ alias_lhs,
+ rhs,
+ direction,
+ Invert::No,
+ ));
// RHS normalizes-to RHS
- candidates.extend(
- evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes).ok(),
- );
+ candidates.extend(evaluate_normalizes_to(
+ self,
+ alias_rhs,
+ lhs,
+ direction,
+ Invert::Yes,
+ ));
// Relate via substs
- candidates.extend(
- self.probe(|ecx| {
- let span = tracing::span!(
- tracing::Level::DEBUG,
- "compute_alias_relate_goal(relate_via_substs)",
- ?alias_lhs,
- ?alias_rhs,
- ?direction
- );
- let _enter = span.enter();
+ let subst_relate_response = self.probe(|ecx| {
+ let span = tracing::span!(
+ tracing::Level::DEBUG,
+ "compute_alias_relate_goal(relate_via_substs)",
+ ?alias_lhs,
+ ?alias_rhs,
+ ?direction
+ );
+ let _enter = span.enter();
- match direction {
- ty::AliasRelationDirection::Equate => {
- ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
- }
- ty::AliasRelationDirection::Subtype => {
- ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
- }
+ match direction {
+ ty::AliasRelationDirection::Equate => {
+ ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
}
+ ty::AliasRelationDirection::Subtype => {
+ ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
+ }
+ }
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
- })
- .ok(),
- );
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ });
+ candidates.extend(subst_relate_response);
debug!(?candidates);
if let Some(merged) = self.try_merge_responses(&candidates) {
Ok(merged)
} else {
- self.flounder(&candidates)
+ // When relating two aliases and we have ambiguity, we prefer
+ // relating the generic arguments of the aliases over normalizing
+ // them. This is necessary for inference during typeck.
+ //
+ // As this is incomplete, we must not do so during coherence.
+ match (self.solver_mode(), subst_relate_response) {
+ (SolverMode::Normal, Ok(response)) => Ok(response),
+ (SolverMode::Normal, Err(NoSolution)) | (SolverMode::Coherence, _) => {
+ self.flounder(&candidates)
+ }
+ }
}
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs
new file mode 100644
index 0000000..a5de4dd
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/opaques.rs
@@ -0,0 +1,67 @@
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
+use rustc_middle::traits::Reveal;
+use rustc_middle::ty;
+use rustc_middle::ty::util::NotUniqueParam;
+
+use super::{EvalCtxt, SolverMode};
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+ pub(super) fn normalize_opaque_type(
+ &mut self,
+ goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ let tcx = self.tcx();
+ let opaque_ty = goal.predicate.projection_ty;
+ let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
+
+ match (goal.param_env.reveal(), self.solver_mode()) {
+ (Reveal::UserFacing, SolverMode::Normal) => {
+ let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
+ return Err(NoSolution);
+ };
+ let opaque_ty =
+ ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
+ // FIXME: at some point we should call queries without defining
+ // new opaque types but having the existing opaque type definitions.
+ // This will require moving this below "Prefer opaques registered already".
+ if !self.can_define_opaque_ty(opaque_ty_def_id) {
+ return Err(NoSolution);
+ }
+ // FIXME: This may have issues when the substs contain aliases...
+ match self.tcx().uses_unique_placeholders_ignoring_regions(opaque_ty.substs) {
+ Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
+ return self.evaluate_added_goals_and_make_canonical_response(
+ Certainty::AMBIGUOUS,
+ );
+ }
+ Err(_) => {
+ return Err(NoSolution);
+ }
+ Ok(()) => {}
+ }
+ // Prefer opaques registered already.
+ let matches = self.unify_existing_opaque_tys(goal.param_env, opaque_ty, expected);
+ if !matches.is_empty() {
+ if let Some(response) = self.try_merge_responses(&matches) {
+ return Ok(response);
+ } else {
+ return self.flounder(&matches);
+ }
+ }
+ // Otherwise, define a new opaque type
+ self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+ (Reveal::UserFacing, SolverMode::Coherence) => {
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+ }
+ (Reveal::All, _) => {
+ // FIXME: Add an assertion that opaque type storage is empty.
+ let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs);
+ self.eq(goal.param_env, expected, actual)?;
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index d322807..7d7dfa2 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -22,19 +22,25 @@
&mut self,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
) -> QueryResult<'tcx> {
- // To only compute normalization once for each projection we only
- // normalize if the expected term is an unconstrained inference variable.
- //
- // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
- // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
- // `U` and equate it with `u32`. This means that we don't need a separate
- // projection cache in the solver.
- if self.term_is_fully_unconstrained(goal) {
- let candidates = self.assemble_and_evaluate_candidates(goal);
- self.merge_candidates(candidates)
- } else {
- self.set_normalizes_to_hack_goal(goal);
- self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ match goal.predicate.projection_ty.kind(self.tcx()) {
+ ty::AliasKind::Projection => {
+ // To only compute normalization once for each projection we only
+ // normalize if the expected term is an unconstrained inference variable.
+ //
+ // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
+ // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
+ // `U` and equate it with `u32`. This means that we don't need a separate
+ // projection cache in the solver.
+ if self.term_is_fully_unconstrained(goal) {
+ let candidates = self.assemble_and_evaluate_candidates(goal);
+ self.merge_candidates(candidates)
+ } else {
+ self.set_normalizes_to_hack_goal(goal);
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+ }
+ ty::AliasKind::Opaque => self.normalize_opaque_type(goal),
+ ty::AliasKind::Inherent => bug!("IATs not supported here yet"),
}
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
index e6941af..56f126e 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
@@ -11,7 +11,7 @@
use super::StackDepth;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::IndexVec;
-use rustc_middle::traits::solve::{CanonicalGoal, QueryResult};
+use rustc_middle::traits::solve::{CanonicalInput, QueryResult};
rustc_index::newtype_index! {
pub struct EntryIndex {}
@@ -34,7 +34,7 @@
// The goal for this entry. Should always be equal to the corresponding goal
// in the lookup table.
- pub(super) goal: CanonicalGoal<'tcx>,
+ pub(super) input: CanonicalInput<'tcx>,
}
pub(super) struct ProvisionalCache<'tcx> {
@@ -42,7 +42,7 @@
// FIXME: This is only used to quickly check whether a given goal
// is in the cache. We should experiment with using something like
// `SsoHashSet` here because in most cases there are only a few entries.
- pub(super) lookup_table: FxHashMap<CanonicalGoal<'tcx>, EntryIndex>,
+ pub(super) lookup_table: FxHashMap<CanonicalInput<'tcx>, EntryIndex>,
}
impl<'tcx> ProvisionalCache<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index c190435..19e4b23 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -8,7 +8,7 @@
use overflow::OverflowData;
use rustc_index::IndexVec;
use rustc_middle::dep_graph::DepKind;
-use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+use rustc_middle::traits::solve::{CanonicalInput, Certainty, MaybeCause, QueryResult};
use rustc_middle::ty::TyCtxt;
use std::{collections::hash_map::Entry, mem};
@@ -19,7 +19,7 @@
}
struct StackElem<'tcx> {
- goal: CanonicalGoal<'tcx>,
+ input: CanonicalInput<'tcx>,
has_been_used: bool,
}
@@ -77,7 +77,7 @@
}
// ...or it depends on a goal with a lower depth.
- let current_goal = self.stack[stack_depth].goal;
+ let current_goal = self.stack[stack_depth].input;
let entry_index = self.provisional_cache.lookup_table[¤t_goal];
self.provisional_cache.entries[entry_index].depth != stack_depth
} else {
@@ -92,20 +92,20 @@
fn try_push_stack(
&mut self,
tcx: TyCtxt<'tcx>,
- goal: CanonicalGoal<'tcx>,
+ input: CanonicalInput<'tcx>,
) -> Result<(), QueryResult<'tcx>> {
// Look at the provisional cache to check for cycles.
let cache = &mut self.provisional_cache;
- match cache.lookup_table.entry(goal) {
+ match cache.lookup_table.entry(input) {
// No entry, simply push this goal on the stack after dealing with overflow.
Entry::Vacant(v) => {
if self.overflow_data.has_overflow(self.stack.len()) {
- return Err(self.deal_with_overflow(tcx, goal));
+ return Err(self.deal_with_overflow(tcx, input));
}
- let depth = self.stack.push(StackElem { goal, has_been_used: false });
- let response = super::response_no_constraints(tcx, goal, Certainty::Yes);
- let entry_index = cache.entries.push(ProvisionalEntry { response, depth, goal });
+ let depth = self.stack.push(StackElem { input, has_been_used: false });
+ let response = super::response_no_constraints(tcx, input, Certainty::Yes);
+ let entry_index = cache.entries.push(ProvisionalEntry { response, depth, input });
v.insert(entry_index);
Ok(())
}
@@ -135,13 +135,13 @@
// the stack is enough.
if self.stack.raw[stack_depth.index()..]
.iter()
- .all(|g| g.goal.value.predicate.is_coinductive(tcx))
+ .all(|g| g.input.value.goal.predicate.is_coinductive(tcx))
{
Err(cache.provisional_result(entry_index))
} else {
Err(super::response_no_constraints(
tcx,
- goal,
+ input,
Certainty::Maybe(MaybeCause::Overflow),
))
}
@@ -161,18 +161,18 @@
/// updated the provisional cache and we have to recompute the current goal.
///
/// FIXME: Refer to the rustc-dev-guide entry once it exists.
- #[instrument(level = "debug", skip(self, actual_goal), ret)]
+ #[instrument(level = "debug", skip(self, actual_input), ret)]
fn try_finalize_goal(
&mut self,
- actual_goal: CanonicalGoal<'tcx>,
+ actual_input: CanonicalInput<'tcx>,
response: QueryResult<'tcx>,
) -> bool {
let stack_elem = self.stack.pop().unwrap();
- let StackElem { goal, has_been_used } = stack_elem;
- assert_eq!(goal, actual_goal);
+ let StackElem { input, has_been_used } = stack_elem;
+ assert_eq!(input, actual_input);
let cache = &mut self.provisional_cache;
- let provisional_entry_index = *cache.lookup_table.get(&goal).unwrap();
+ let provisional_entry_index = *cache.lookup_table.get(&input).unwrap();
let provisional_entry = &mut cache.entries[provisional_entry_index];
// We eagerly update the response in the cache here. If we have to reevaluate
// this goal we use the new response when hitting a cycle, and we definitely
@@ -194,7 +194,7 @@
cache.entries.truncate(provisional_entry_index.index() + 1);
// ...and finally push our goal back on the stack and reevaluate it.
- self.stack.push(StackElem { goal, has_been_used: false });
+ self.stack.push(StackElem { input, has_been_used: false });
false
} else {
true
@@ -204,17 +204,17 @@
pub(super) fn with_new_goal(
&mut self,
tcx: TyCtxt<'tcx>,
- canonical_goal: CanonicalGoal<'tcx>,
+ canonical_input: CanonicalInput<'tcx>,
mut loop_body: impl FnMut(&mut Self) -> QueryResult<'tcx>,
) -> QueryResult<'tcx> {
if self.should_use_global_cache() {
- if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_goal, tcx) {
- debug!(?canonical_goal, ?result, "cache hit");
+ if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) {
+ debug!(?canonical_input, ?result, "cache hit");
return result;
}
}
- match self.try_push_stack(tcx, canonical_goal) {
+ match self.try_push_stack(tcx, canonical_input) {
Ok(()) => {}
// Our goal is already on the stack, eager return.
Err(response) => return response,
@@ -226,19 +226,19 @@
let (result, dep_node) = tcx.dep_graph.with_anon_task(tcx, DepKind::TraitSelect, || {
self.repeat_while_none(
|this| {
- let result = this.deal_with_overflow(tcx, canonical_goal);
+ let result = this.deal_with_overflow(tcx, canonical_input);
let _ = this.stack.pop().unwrap();
result
},
|this| {
let result = loop_body(this);
- this.try_finalize_goal(canonical_goal, result).then(|| result)
+ this.try_finalize_goal(canonical_input, result).then(|| result)
},
)
});
let cache = &mut self.provisional_cache;
- let provisional_entry_index = *cache.lookup_table.get(&canonical_goal).unwrap();
+ let provisional_entry_index = *cache.lookup_table.get(&canonical_input).unwrap();
let provisional_entry = &mut cache.entries[provisional_entry_index];
let depth = provisional_entry.depth;
@@ -254,13 +254,13 @@
// cycle participants without moving them to the global cache.
let other_cycle_participants = provisional_entry_index.index() + 1;
for (i, entry) in cache.entries.drain_enumerated(other_cycle_participants..) {
- let actual_index = cache.lookup_table.remove(&entry.goal);
+ let actual_index = cache.lookup_table.remove(&entry.input);
debug_assert_eq!(Some(i), actual_index);
debug_assert!(entry.depth == depth);
}
let current_goal = cache.entries.pop().unwrap();
- let actual_index = cache.lookup_table.remove(¤t_goal.goal);
+ let actual_index = cache.lookup_table.remove(¤t_goal.input);
debug_assert_eq!(Some(provisional_entry_index), actual_index);
debug_assert!(current_goal.depth == depth);
@@ -274,7 +274,7 @@
let can_cache = !self.overflow_data.did_overflow() || self.stack.is_empty();
if self.should_use_global_cache() && can_cache {
tcx.new_solver_evaluation_cache.insert(
- current_goal.goal,
+ current_goal.input,
dep_node,
current_goal.response,
);
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 644bfd3..f722f28 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -358,7 +358,7 @@
// Can only unsize to an object-safe type
if data
.principal_def_id()
- .map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
+ .is_some_and(|def_id| !tcx.check_is_object_safe(def_id))
{
return Err(NoSolution);
}
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 183c240..62d2aad 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -834,8 +834,10 @@
| ty::PredicateKind::Subtype(..)
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::ConstEvaluatable(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+ | ty::PredicateKind::Coerce(..) => {}
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
+ bug!("predicate should only exist in the environment: {bound_predicate:?}")
+ }
ty::PredicateKind::Ambiguous => return false,
};
}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 969e5fa..e8c5a8f 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -17,9 +17,10 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_infer::infer::{DefineOpaqueTypes, DefiningAnchor, InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
@@ -706,7 +707,7 @@
}
ty::Dynamic(tt, ..) => {
let principal = tt.principal().map(|p| p.def_id());
- if principal.map_or(false, |p| self.def_id_is_local(p)) {
+ if principal.is_some_and(|p| self.def_id_is_local(p)) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else {
self.found_non_local_ty(ty)
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 000427b..2c5ffd6 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -14,11 +14,11 @@
};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::query::Fallible;
use rustc_infer::traits::{
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
};
use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::TypeFoldable;
@@ -235,7 +235,7 @@
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
- ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+ ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index dc43a3d..a10ecec 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -437,7 +437,7 @@
// 1) strictly implied by another error.
// 2) implied by an error with a smaller index.
for error2 in error_set {
- if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+ if error2.index.is_some_and(|index2| is_suppressed[index2]) {
// Avoid errors being suppressed by already-suppressed
// errors, to prevent all errors from being suppressed
// at once.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 83511e8..82bad96 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -420,7 +420,7 @@
) {
if hir_generics.where_clause_span.from_expansion()
|| hir_generics.where_clause_span.desugaring_kind().is_some()
- || projection.map_or(false, |projection| tcx.opt_rpitit_info(projection.def_id).is_some())
+ || projection.is_some_and(|projection| tcx.opt_rpitit_info(projection.def_id).is_some())
{
return;
}
@@ -2936,7 +2936,7 @@
"note_obligation_cause_code: check for async fn"
);
if is_future
- && obligated_types.last().map_or(false, |ty| match ty.kind() {
+ && obligated_types.last().is_some_and(|ty| match ty.kind() {
ty::Generator(last_def_id, ..) => {
tcx.generator_is_async(*last_def_id)
}
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 0db8023..f8d056e 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,9 +1,9 @@
use crate::infer::InferCtxt;
-use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
-use crate::traits::query::NoSolution;
use crate::traits::{ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
+use rustc_infer::infer::InferOk;
+use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints};
use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
use rustc_span::def_id::LocalDefId;
@@ -68,24 +68,29 @@
return vec![];
}
- let span = self.tcx.def_span(body_id);
- let result = param_env
- .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
- .fully_perform(self);
- let result = match result {
- Ok(r) => r,
- Err(NoSolution) => {
- self.tcx.sess.delay_span_bug(
- span,
- "implied_outlives_bounds failed to solve all obligations",
- );
- return vec![];
- }
+ let mut canonical_var_values = OriginalQueryValues::default();
+ let canonical_ty =
+ self.canonicalize_query_keep_static(param_env.and(ty), &mut canonical_var_values);
+ let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else {
+ return vec![];
};
- let TypeOpOutput { output, constraints, .. } = result;
+ let mut constraints = QueryRegionConstraints::default();
+ let Ok(InferOk { value, obligations }) = self
+ .instantiate_nll_query_response_and_region_obligations(
+ &ObligationCause::dummy(),
+ param_env,
+ &canonical_var_values,
+ canonical_result,
+ &mut constraints,
+ ) else {
+ return vec![];
+ };
+ assert_eq!(&obligations, &[]);
- if let Some(constraints) = constraints {
+ if !constraints.is_empty() {
+ let span = self.tcx.def_span(body_id);
+
debug!(?constraints);
if !constraints.member_constraints.is_empty() {
span_bug!(span, "{:#?}", constraints.member_constraints);
@@ -112,7 +117,7 @@
}
};
- output
+ value
}
fn implied_bounds_tys(
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 455b53b..4e4172e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -1,6 +1,11 @@
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use crate::traits::query::normalize::QueryNormalizeExt;
+use crate::traits::query::NoSolution;
+use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
-pub use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
+use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
+use rustc_span::source_map::{Span, DUMMY_SP};
/// This returns true if the type `ty` is "trivial" for
/// dropck-outlives -- that is, if it doesn't require any types to
@@ -71,3 +76,263 @@
| ty::Generator(..) => false,
}
}
+
+pub fn compute_dropck_outlives_inner<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
+ let tcx = ocx.infcx.tcx;
+ let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+ let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+ // A stack of types left to process. Each round, we pop
+ // something from the stack and invoke
+ // `dtorck_constraint_for_ty_inner`. This may produce new types that
+ // have to be pushed on the stack. This continues until we have explored
+ // all the reachable types from the type `for_ty`.
+ //
+ // Example: Imagine that we have the following code:
+ //
+ // ```rust
+ // struct A {
+ // value: B,
+ // children: Vec<A>,
+ // }
+ //
+ // struct B {
+ // value: u32
+ // }
+ //
+ // fn f() {
+ // let a: A = ...;
+ // ..
+ // } // here, `a` is dropped
+ // ```
+ //
+ // at the point where `a` is dropped, we need to figure out
+ // which types inside of `a` contain region data that may be
+ // accessed by any destructors in `a`. We begin by pushing `A`
+ // onto the stack, as that is the type of `a`. We will then
+ // invoke `dtorck_constraint_for_ty_inner` which will expand `A`
+ // into the types of its fields `(B, Vec<A>)`. These will get
+ // pushed onto the stack. Eventually, expanding `Vec<A>` will
+ // lead to us trying to push `A` a second time -- to prevent
+ // infinite recursion, we notice that `A` was already pushed
+ // once and stop.
+ let mut ty_stack = vec![(for_ty, 0)];
+
+ // Set used to detect infinite recursion.
+ let mut ty_set = FxHashSet::default();
+
+ let cause = ObligationCause::dummy();
+ let mut constraints = DropckConstraint::empty();
+ while let Some((ty, depth)) = ty_stack.pop() {
+ debug!(
+ "{} kinds, {} overflows, {} ty_stack",
+ result.kinds.len(),
+ result.overflows.len(),
+ ty_stack.len()
+ );
+ dtorck_constraint_for_ty_inner(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+ // "outlives" represent types/regions that may be touched
+ // by a destructor.
+ result.kinds.append(&mut constraints.outlives);
+ result.overflows.append(&mut constraints.overflows);
+
+ // If we have even one overflow, we should stop trying to evaluate further --
+ // chances are, the subsequent overflows for this evaluation won't provide useful
+ // information and will just decrease the speed at which we can emit these errors
+ // (since we'll be printing for just that much longer for the often enormous types
+ // that result here).
+ if !result.overflows.is_empty() {
+ break;
+ }
+
+ // dtorck types are "types that will get dropped but which
+ // do not themselves define a destructor", more or less. We have
+ // to push them onto the stack to be expanded.
+ for ty in constraints.dtorck_types.drain(..) {
+ let Normalized { value: ty, obligations } =
+ ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
+ ocx.register_obligations(obligations);
+
+ debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+ match ty.kind() {
+ // All parameters live for the duration of the
+ // function.
+ ty::Param(..) => {}
+
+ // A projection that we couldn't resolve - it
+ // might have a destructor.
+ ty::Alias(..) => {
+ result.kinds.push(ty.into());
+ }
+
+ _ => {
+ if ty_set.insert(ty) {
+ ty_stack.push((ty, depth + 1));
+ }
+ }
+ }
+ }
+ }
+
+ debug!("dropck_outlives: result = {:#?}", result);
+ Ok(result)
+}
+
+/// Returns a set of constraints that needs to be satisfied in
+/// order for `ty` to be valid for destruction.
+pub fn dtorck_constraint_for_ty_inner<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ span: Span,
+ for_ty: Ty<'tcx>,
+ depth: usize,
+ ty: Ty<'tcx>,
+ constraints: &mut DropckConstraint<'tcx>,
+) -> Result<(), NoSolution> {
+ debug!("dtorck_constraint_for_ty_inner({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
+
+ if !tcx.recursion_limit().value_within_limit(depth) {
+ constraints.overflows.push(ty);
+ return Ok(());
+ }
+
+ if trivial_dropck_outlives(tcx, ty) {
+ return Ok(());
+ }
+
+ match ty.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Str
+ | ty::Never
+ | ty::Foreign(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(_)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..) => {
+ // these types never have a destructor
+ }
+
+ ty::Array(ety, _) | ty::Slice(ety) => {
+ // single-element containers, behave like their element
+ rustc_data_structures::stack::ensure_sufficient_stack(|| {
+ dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, *ety, constraints)
+ })?;
+ }
+
+ ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
+ for ty in tys.iter() {
+ dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
+ }
+ Ok::<_, NoSolution>(())
+ })?,
+
+ ty::Closure(_, substs) => {
+ if !substs.as_closure().is_valid() {
+ // By the time this code runs, all type variables ought to
+ // be fully resolved.
+
+ tcx.sess.delay_span_bug(
+ span,
+ format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
+ );
+ return Err(NoSolution);
+ }
+
+ rustc_data_structures::stack::ensure_sufficient_stack(|| {
+ for ty in substs.as_closure().upvar_tys() {
+ dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
+ }
+ Ok::<_, NoSolution>(())
+ })?
+ }
+
+ ty::Generator(_, substs, _movability) => {
+ // rust-lang/rust#49918: types can be constructed, stored
+ // in the interior, and sit idle when generator yields
+ // (and is subsequently dropped).
+ //
+ // It would be nice to descend into interior of a
+ // generator to determine what effects dropping it might
+ // have (by looking at any drop effects associated with
+ // its interior).
+ //
+ // However, the interior's representation uses things like
+ // GeneratorWitness that explicitly assume they are not
+ // traversed in such a manner. So instead, we will
+ // simplify things for now by treating all generators as
+ // if they were like trait objects, where its upvars must
+ // all be alive for the generator's (potential)
+ // destructor.
+ //
+ // In particular, skipping over `_interior` is safe
+ // because any side-effects from dropping `_interior` can
+ // only take place through references with lifetimes
+ // derived from lifetimes attached to the upvars and resume
+ // argument, and we *do* incorporate those here.
+
+ if !substs.as_generator().is_valid() {
+ // By the time this code runs, all type variables ought to
+ // be fully resolved.
+ tcx.sess.delay_span_bug(
+ span,
+ format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
+ );
+ return Err(NoSolution);
+ }
+
+ constraints.outlives.extend(
+ substs
+ .as_generator()
+ .upvar_tys()
+ .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
+ );
+ constraints.outlives.push(substs.as_generator().resume_ty().into());
+ }
+
+ ty::Adt(def, substs) => {
+ let DropckConstraint { dtorck_types, outlives, overflows } =
+ tcx.at(span).adt_dtorck_constraint(def.did())?;
+ // FIXME: we can try to recursively `dtorck_constraint_on_ty`
+ // there, but that needs some way to handle cycles.
+ constraints
+ .dtorck_types
+ .extend(dtorck_types.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
+ constraints
+ .outlives
+ .extend(outlives.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
+ constraints
+ .overflows
+ .extend(overflows.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
+ }
+
+ // Objects must be alive in order for their destructor
+ // to be called.
+ ty::Dynamic(..) => {
+ constraints.outlives.push(ty.into());
+ }
+
+ // Types that can't be resolved. Pass them forward.
+ ty::Alias(..) | ty::Param(..) => {
+ constraints.dtorck_types.push(ty);
+ }
+
+ ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
+ // By the time this code runs, all type variables ought to
+ // be fully resolved.
+ return Err(NoSolution);
+ }
+ }
+
+ Ok(())
+}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index e6db96c..01d7a1e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -1,8 +1,13 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
-use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use crate::traits::ObligationCtxt;
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_infer::traits::Obligation;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType};
pub use rustc_middle::traits::query::type_op::AscribeUserType;
+use rustc_span::{Span, DUMMY_SP};
impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
type QueryResponse = ();
@@ -17,7 +22,119 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_ascribe_user_type(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ type_op_ascribe_user_type_with_span(ocx, key, None)
+ }
+}
+
+/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
+/// this query can be re-run to better track the span of the obligation cause, and improve the error
+/// message. Do not call directly unless you're in that very specific context.
+pub fn type_op_ascribe_user_type_with_span<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
+ span: Option<Span>,
+) -> Result<(), NoSolution> {
+ let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
+ debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
+ let span = span.unwrap_or(DUMMY_SP);
+ match user_ty {
+ UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
+ UserType::TypeOf(def_id, user_substs) => {
+ relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
+ }
+ };
+ Ok(())
+}
+
+#[instrument(level = "debug", skip(ocx, param_env, span))]
+fn relate_mir_and_user_ty<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span,
+ mir_ty: Ty<'tcx>,
+ user_ty: Ty<'tcx>,
+) -> Result<(), NoSolution> {
+ let cause = ObligationCause::dummy_with_span(span);
+ let user_ty = ocx.normalize(&cause, param_env, user_ty);
+ ocx.eq(&cause, param_env, mir_ty, user_ty)?;
+
+ // FIXME(#104764): We should check well-formedness before normalization.
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
+ ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
+ Ok(())
+}
+
+#[instrument(level = "debug", skip(ocx, param_env, span))]
+fn relate_mir_and_user_substs<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span,
+ mir_ty: Ty<'tcx>,
+ def_id: DefId,
+ user_substs: UserSubsts<'tcx>,
+) -> Result<(), NoSolution> {
+ let param_env = param_env.without_const();
+ let UserSubsts { user_self_ty, substs } = user_substs;
+ let tcx = ocx.infcx.tcx;
+ let cause = ObligationCause::dummy_with_span(span);
+
+ let ty = tcx.type_of(def_id).subst(tcx, substs);
+ let ty = ocx.normalize(&cause, param_env, ty);
+ debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
+
+ ocx.eq(&cause, param_env, mir_ty, ty)?;
+
+ // Prove the predicates coming along with `def_id`.
+ //
+ // Also, normalize the `instantiated_predicates`
+ // because otherwise we wind up with duplicate "type
+ // outlives" error messages.
+ let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+
+ debug!(?instantiated_predicates);
+ for (instantiated_predicate, predicate_span) in instantiated_predicates {
+ let span = if span == DUMMY_SP { predicate_span } else { span };
+ let cause = ObligationCause::new(
+ span,
+ CRATE_DEF_ID,
+ ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
+ );
+ let instantiated_predicate =
+ ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
+
+ ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
+ }
+
+ if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
+ let self_ty = ocx.normalize(&cause, param_env, self_ty);
+ let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
+ let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
+
+ ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
+ ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
+ }
+
+ // In addition to proving the predicates, we have to
+ // prove that `ty` is well-formed -- this is because
+ // the WF of `ty` is predicated on the substs being
+ // well-formed, and we haven't proven *that*. We don't
+ // want to prove the WF of types from `substs` directly because they
+ // haven't been normalized.
+ //
+ // FIXME(nmatsakis): Well, perhaps we should normalize
+ // them? This would only be relevant if some input
+ // type were ill-formed but did not appear in `ty`,
+ // which...could happen with normalization...
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
+ ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
+ Ok(())
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 1f8e756..6d8d210 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,32 +1,32 @@
use crate::infer::canonical::query_response;
-use crate::infer::{InferCtxt, InferOk};
+use crate::infer::InferCtxt;
use crate::traits::query::type_op::TypeOpOutput;
-use crate::traits::query::Fallible;
use crate::traits::ObligationCtxt;
+use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::region_constraints::RegionConstraintData;
+use rustc_middle::traits::query::NoSolution;
use rustc_span::source_map::DUMMY_SP;
+use rustc_span::Span;
use std::fmt;
-pub struct CustomTypeOp<F, G> {
+pub struct CustomTypeOp<F> {
closure: F,
- description: G,
+ description: &'static str,
}
-impl<F, G> CustomTypeOp<F, G> {
- pub fn new<'tcx, R>(closure: F, description: G) -> Self
+impl<F> CustomTypeOp<F> {
+ pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
where
- F: FnOnce(&InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
- G: Fn() -> String,
+ F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
{
CustomTypeOp { closure, description }
}
}
-impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
+impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
where
- F: for<'a, 'cx> FnOnce(&'a InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
- G: Fn() -> String,
+ F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
{
type Output = R;
/// We can't do any custom error reporting for `CustomTypeOp`, so
@@ -36,21 +36,22 @@
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
- fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(
+ self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
if cfg!(debug_assertions) {
info!("fully_perform({:?})", self);
}
- Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0)
+ Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
}
}
-impl<F, G> fmt::Debug for CustomTypeOp<F, G>
-where
- G: Fn() -> String,
-{
+impl<F> fmt::Debug for CustomTypeOp<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", (self.description)())
+ self.description.fmt(f)
}
}
@@ -58,8 +59,10 @@
/// constraints that result, creating query-region-constraints.
pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
infcx: &InferCtxt<'tcx>,
- op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
+ op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
+ name: &'static str,
+ span: Span,
+) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> {
// During NLL, we expect that nobody will register region
// obligations **except** as part of a custom type op (and, at the
// end of each custom type op, we scrape out the region
@@ -72,16 +75,21 @@
pre_obligations,
);
- let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
- let ocx = ObligationCtxt::new(infcx);
- ocx.register_obligations(obligations);
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- infcx.tcx.sess.diagnostic().delay_span_bug(
- DUMMY_SP,
- format!("errors selecting obligation during MIR typeck: {:?}", errors),
- );
- }
+ let value = infcx.commit_if_ok(|_| {
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
+ let value = op(&ocx).map_err(|_| {
+ infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
+ })?;
+ let errors = ocx.select_all_or_error();
+ if errors.is_empty() {
+ Ok(value)
+ } else {
+ Err(infcx.tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("errors selecting obligation during MIR typeck: {:?}", errors),
+ ))
+ }
+ })?;
let region_obligations = infcx.take_registered_region_obligations();
let region_constraint_data = infcx.take_and_reset_region_constraints();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
index 8c9b961..f658930 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
@@ -1,5 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::Eq;
@@ -17,7 +19,15 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_eq(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ ocx.eq(&ObligationCause::dummy(), key.param_env, key.value.a, key.value.b)?;
+ Ok(())
+ }
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 18d7c9b1..9989fc9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,7 +1,15 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::query::NoSolution;
+use crate::traits::wf;
+use crate::traits::ObligationCtxt;
+
+use rustc_infer::infer::canonical::Canonical;
+use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
use rustc_infer::traits::query::OutlivesBound;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::infer::canonical::CanonicalQueryResponse;
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::CRATE_DEF_ID;
+use rustc_span::source_map::DUMMY_SP;
+use smallvec::{smallvec, SmallVec};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ImpliedOutlivesBounds<'tcx> {
@@ -28,7 +36,7 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
// FIXME this `unchecked_map` is only necessary because the
// query is defined as taking a `ParamEnvAnd<Ty>`; it should
// take an `ImpliedOutlivesBounds` instead
@@ -39,4 +47,169 @@
tcx.implied_outlives_bounds(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty)
+ }
+}
+
+pub fn compute_implied_outlives_bounds_inner<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
+ let tcx = ocx.infcx.tcx;
+
+ // Sometimes when we ask what it takes for T: WF, we get back that
+ // U: WF is required; in that case, we push U onto this stack and
+ // process it next. Because the resulting predicates aren't always
+ // guaranteed to be a subset of the original type, so we need to store the
+ // WF args we've computed in a set.
+ let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
+ let mut wf_args = vec![ty.into()];
+
+ let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
+ vec![];
+
+ while let Some(arg) = wf_args.pop() {
+ if !checked_wf_args.insert(arg) {
+ continue;
+ }
+
+ // Compute the obligations for `arg` to be well-formed. If `arg` is
+ // an unresolved inference variable, just substituted an empty set
+ // -- because the return type here is going to be things we *add*
+ // to the environment, it's always ok for this set to be smaller
+ // than the ultimate set. (Note: normally there won't be
+ // unresolved inference variables here anyway, but there might be
+ // during typeck under some circumstances.)
+ //
+ // FIXME(@lcnr): It's not really "always fine", having fewer implied
+ // bounds can be backward incompatible, e.g. #101951 was caused by
+ // us not dealing with inference vars in `TypeOutlives` predicates.
+ let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
+ .unwrap_or_default();
+
+ for obligation in obligations {
+ debug!(?obligation);
+ assert!(!obligation.has_escaping_bound_vars());
+
+ // While these predicates should all be implied by other parts of
+ // the program, they are still relevant as they may constrain
+ // inference variables, which is necessary to add the correct
+ // implied bounds in some cases, mostly when dealing with projections.
+ //
+ // Another important point here: we only register `Projection`
+ // predicates, since otherwise we might register outlives
+ // predicates containing inference variables, and we don't
+ // learn anything new from those.
+ if obligation.predicate.has_non_region_infer() {
+ match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::AliasRelate(..) => {
+ ocx.register_obligation(obligation.clone());
+ }
+ _ => {}
+ }
+ }
+
+ let pred = match obligation.predicate.kind().no_bound_vars() {
+ None => continue,
+ Some(pred) => pred,
+ };
+ match pred {
+ ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
+ // if we ever support that
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Coerce(..)
+ | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasRelate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+
+ // We need to search through *all* WellFormed predicates
+ ty::PredicateKind::WellFormed(arg) => {
+ wf_args.push(arg);
+ }
+
+ // We need to register region relationships
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
+ r_a,
+ r_b,
+ ))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
+
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty_a,
+ r_b,
+ ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
+ }
+ }
+ }
+
+ // This call to `select_all_or_error` is necessary to constrain inference variables, which we
+ // use further down when computing the implied bounds.
+ match ocx.select_all_or_error().as_slice() {
+ [] => (),
+ _ => return Err(NoSolution),
+ }
+
+ // We lazily compute the outlives components as
+ // `select_all_or_error` constrains inference variables.
+ let implied_bounds = outlives_bounds
+ .into_iter()
+ .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
+ ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
+ ty::GenericArgKind::Type(ty_a) => {
+ let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
+ let mut components = smallvec![];
+ push_outlives_components(tcx, ty_a, &mut components);
+ implied_bounds_from_components(r_b, components)
+ }
+ ty::GenericArgKind::Const(_) => unreachable!(),
+ })
+ .collect();
+
+ Ok(implied_bounds)
+}
+
+/// When we have an implied bound that `T: 'a`, we can further break
+/// this down to determine what relationships would have to hold for
+/// `T: 'a` to hold. We get to assume that the caller has validated
+/// those relationships.
+fn implied_bounds_from_components<'tcx>(
+ sub_region: ty::Region<'tcx>,
+ sup_components: SmallVec<[Component<'tcx>; 4]>,
+) -> Vec<OutlivesBound<'tcx>> {
+ sup_components
+ .into_iter()
+ .filter_map(|component| {
+ match component {
+ Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
+ Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
+ Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
+ Component::EscapingAlias(_) =>
+ // If the projection has escaping regions, don't
+ // try to infer any implied bounds even for its
+ // free components. This is conservative, because
+ // the caller will still have to prove that those
+ // free components outlive `sub_region`. But the
+ // idea is that the WAY that the caller proves
+ // that may change in the future and we want to
+ // give ourselves room to get smarter here.
+ {
+ None
+ }
+ Component::UnresolvedInferenceVariable(..) => None,
+ }
+ })
+ .collect()
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 9e8bc8b..642fdec 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -2,13 +2,14 @@
Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
};
use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, ObligationCtxt};
+use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::canonical::Certainty;
-use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::PredicateObligations;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use rustc_span::Span;
use std::fmt;
pub mod ascribe_user_type;
@@ -22,6 +23,8 @@
pub use rustc_middle::traits::query::type_op::*;
+use self::custom::scrape_region_constraints;
+
/// "Type ops" are used in NLL to perform some particular action and
/// extract out the resulting region constraints (or an error if it
/// cannot be completed).
@@ -32,7 +35,11 @@
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
- fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+ fn fully_perform(
+ self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
}
/// The output from performing a type op
@@ -74,18 +81,32 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>>;
+ ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
+
+ /// In the new trait solver, we already do caching in the solver itself,
+ /// so there's no need to canonicalize and cache via the query system.
+ /// Additionally, even if we were to canonicalize, we'd still need to
+ /// make sure to feed it predefined opaque types and the defining anchor
+ /// and that would require duplicating all of the tcx queries. Instead,
+ /// just perform these ops locally.
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution>;
fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
- ) -> Fallible<(
- Self::QueryResponse,
- Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
- PredicateObligations<'tcx>,
- Certainty,
- )> {
+ ) -> Result<
+ (
+ Self::QueryResponse,
+ Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+ PredicateObligations<'tcx>,
+ Certainty,
+ ),
+ NoSolution,
+ > {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok((result, None, vec![], Certainty::Proven));
}
@@ -120,10 +141,26 @@
type Output = Q::QueryResponse;
type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
- fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(
+ self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+ if infcx.tcx.trait_solver_next() {
+ return Ok(scrape_region_constraints(
+ infcx,
+ |ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self),
+ "query type op",
+ span,
+ )?
+ .0);
+ }
+
let mut region_constraints = QueryRegionConstraints::default();
let (output, error_info, mut obligations, _) =
- Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+ Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+ infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
+ })?;
// Typically, instantiating NLL query results does not
// create obligations. However, in some cases there
@@ -151,7 +188,10 @@
}
}
if !progress {
- return Err(NoSolution);
+ return Err(infcx.tcx.sess.delay_span_bug(
+ span,
+ format!("ambiguity processing {obligations:?} from {self:?}"),
+ ));
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 5b216c0..57ca14a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,5 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use std::fmt;
@@ -19,23 +21,31 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
T::type_op_method(tcx, canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ // FIXME(-Ztrait-solver=next): shouldn't be using old normalizer
+ Ok(ocx.normalize(&ObligationCause::dummy(), key.param_env, key.value.value))
+ }
}
pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self>>;
+ ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
}
impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_ty(canonicalized)
}
}
@@ -44,7 +54,7 @@
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_predicate(canonicalized)
}
}
@@ -53,7 +63,7 @@
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_poly_fn_sig(canonicalized)
}
}
@@ -62,7 +72,7 @@
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_fn_sig(canonicalized)
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 21ef4e2..9889426 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -1,6 +1,9 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
-use crate::traits::query::Fallible;
+use crate::traits::query::dropck_outlives::{
+ compute_dropck_outlives_inner, trivial_dropck_outlives,
+};
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -27,7 +30,7 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
// Subtle: note that we are not invoking
// `infcx.at(...).dropck_outlives(...)` here, but rather the
// underlying `dropck_outlives` query. This same underlying
@@ -48,4 +51,11 @@
tcx.dropck_outlives(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ compute_dropck_outlives_inner(ocx, key.param_env.and(key.value.dropped_ty))
+ }
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index baa2fbb..47850bc 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,5 +1,8 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_infer::traits::Obligation;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::ProvePredicate;
@@ -33,7 +36,20 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_prove_predicate(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ ocx.register_obligation(Obligation::new(
+ ocx.infcx.tcx,
+ ObligationCause::dummy(),
+ key.param_env,
+ key.value.predicate,
+ ));
+ Ok(())
+ }
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
index c51292e..10976d5 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
@@ -1,5 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::Subtype;
@@ -14,7 +16,15 @@
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+ ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_subtype(canonicalized)
}
+
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution> {
+ ocx.sub(&ObligationCause::dummy(), key.param_env, key.value.sub, key.value.sup)?;
+ Ok(())
+ }
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b366bbd..3baf1c9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1793,12 +1793,12 @@
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
- .map_or(false, |InferOk { obligations, value: () }| {
+ .is_ok_and(|InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
nested_obligations.into_iter().chain(obligations),
)
- .map_or(false, |res| res.may_apply())
+ .is_ok_and(|res| res.may_apply())
});
if is_match {
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 2f9e480..e447ab9 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -679,7 +679,7 @@
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
- bug!("unexpected predicate {}", &self)
+ bug!("unexpected predicate {self}")
}
};
value.map(|value| chalk_ir::Binders::new(binders, value))
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 6f81d34..ddba03b 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -3,9 +3,9 @@
// seems likely that they should eventually be merged into more
// general routines.
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
-use rustc_middle::traits::CodegenObligationError;
+use rustc_middle::traits::{CodegenObligationError, DefiningAnchor};
use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::{
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 83f6c7d..f35c14e 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -3,17 +3,14 @@
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
+use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
-use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_middle::ty::TyCtxt;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
use rustc_trait_selection::traits::query::dropck_outlives::{
- DropckConstraint, DropckOutlivesResult,
+ compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
};
-use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_trait_selection::traits::{Normalized, ObligationCause};
pub(crate) fn provide(p: &mut Providers) {
*p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
@@ -26,263 +23,10 @@
debug!("dropck_outlives(goal={:#?})", canonical_goal);
tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
- let tcx = ocx.infcx.tcx;
- let ParamEnvAnd { param_env, value: for_ty } = goal;
-
- let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
- // A stack of types left to process. Each round, we pop
- // something from the stack and invoke
- // `dtorck_constraint_for_ty`. This may produce new types that
- // have to be pushed on the stack. This continues until we have explored
- // all the reachable types from the type `for_ty`.
- //
- // Example: Imagine that we have the following code:
- //
- // ```rust
- // struct A {
- // value: B,
- // children: Vec<A>,
- // }
- //
- // struct B {
- // value: u32
- // }
- //
- // fn f() {
- // let a: A = ...;
- // ..
- // } // here, `a` is dropped
- // ```
- //
- // at the point where `a` is dropped, we need to figure out
- // which types inside of `a` contain region data that may be
- // accessed by any destructors in `a`. We begin by pushing `A`
- // onto the stack, as that is the type of `a`. We will then
- // invoke `dtorck_constraint_for_ty` which will expand `A`
- // into the types of its fields `(B, Vec<A>)`. These will get
- // pushed onto the stack. Eventually, expanding `Vec<A>` will
- // lead to us trying to push `A` a second time -- to prevent
- // infinite recursion, we notice that `A` was already pushed
- // once and stop.
- let mut ty_stack = vec![(for_ty, 0)];
-
- // Set used to detect infinite recursion.
- let mut ty_set = FxHashSet::default();
-
- let cause = ObligationCause::dummy();
- let mut constraints = DropckConstraint::empty();
- while let Some((ty, depth)) = ty_stack.pop() {
- debug!(
- "{} kinds, {} overflows, {} ty_stack",
- result.kinds.len(),
- result.overflows.len(),
- ty_stack.len()
- );
- dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
- // "outlives" represent types/regions that may be touched
- // by a destructor.
- result.kinds.append(&mut constraints.outlives);
- result.overflows.append(&mut constraints.overflows);
-
- // If we have even one overflow, we should stop trying to evaluate further --
- // chances are, the subsequent overflows for this evaluation won't provide useful
- // information and will just decrease the speed at which we can emit these errors
- // (since we'll be printing for just that much longer for the often enormous types
- // that result here).
- if !result.overflows.is_empty() {
- break;
- }
-
- // dtorck types are "types that will get dropped but which
- // do not themselves define a destructor", more or less. We have
- // to push them onto the stack to be expanded.
- for ty in constraints.dtorck_types.drain(..) {
- let Normalized { value: ty, obligations } =
- ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
- ocx.register_obligations(obligations);
-
- debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
- match ty.kind() {
- // All parameters live for the duration of the
- // function.
- ty::Param(..) => {}
-
- // A projection that we couldn't resolve - it
- // might have a destructor.
- ty::Alias(..) => {
- result.kinds.push(ty.into());
- }
-
- _ => {
- if ty_set.insert(ty) {
- ty_stack.push((ty, depth + 1));
- }
- }
- }
- }
- }
-
- debug!("dropck_outlives: result = {:#?}", result);
- Ok(result)
+ compute_dropck_outlives_inner(ocx, goal)
})
}
-/// Returns a set of constraints that needs to be satisfied in
-/// order for `ty` to be valid for destruction.
-fn dtorck_constraint_for_ty<'tcx>(
- tcx: TyCtxt<'tcx>,
- span: Span,
- for_ty: Ty<'tcx>,
- depth: usize,
- ty: Ty<'tcx>,
- constraints: &mut DropckConstraint<'tcx>,
-) -> Result<(), NoSolution> {
- debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
-
- if !tcx.recursion_limit().value_within_limit(depth) {
- constraints.overflows.push(ty);
- return Ok(());
- }
-
- if trivial_dropck_outlives(tcx, ty) {
- return Ok(());
- }
-
- match ty.kind() {
- ty::Bool
- | ty::Char
- | ty::Int(_)
- | ty::Uint(_)
- | ty::Float(_)
- | ty::Str
- | ty::Never
- | ty::Foreign(..)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::GeneratorWitness(..)
- | ty::GeneratorWitnessMIR(..) => {
- // these types never have a destructor
- }
-
- ty::Array(ety, _) | ty::Slice(ety) => {
- // single-element containers, behave like their element
- rustc_data_structures::stack::ensure_sufficient_stack(|| {
- dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, *ety, constraints)
- })?;
- }
-
- ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
- for ty in tys.iter() {
- dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
- }
- Ok::<_, NoSolution>(())
- })?,
-
- ty::Closure(_, substs) => {
- if !substs.as_closure().is_valid() {
- // By the time this code runs, all type variables ought to
- // be fully resolved.
-
- tcx.sess.delay_span_bug(
- span,
- format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
- );
- return Err(NoSolution);
- }
-
- rustc_data_structures::stack::ensure_sufficient_stack(|| {
- for ty in substs.as_closure().upvar_tys() {
- dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
- }
- Ok::<_, NoSolution>(())
- })?
- }
-
- ty::Generator(_, substs, _movability) => {
- // rust-lang/rust#49918: types can be constructed, stored
- // in the interior, and sit idle when generator yields
- // (and is subsequently dropped).
- //
- // It would be nice to descend into interior of a
- // generator to determine what effects dropping it might
- // have (by looking at any drop effects associated with
- // its interior).
- //
- // However, the interior's representation uses things like
- // GeneratorWitness that explicitly assume they are not
- // traversed in such a manner. So instead, we will
- // simplify things for now by treating all generators as
- // if they were like trait objects, where its upvars must
- // all be alive for the generator's (potential)
- // destructor.
- //
- // In particular, skipping over `_interior` is safe
- // because any side-effects from dropping `_interior` can
- // only take place through references with lifetimes
- // derived from lifetimes attached to the upvars and resume
- // argument, and we *do* incorporate those here.
-
- if !substs.as_generator().is_valid() {
- // By the time this code runs, all type variables ought to
- // be fully resolved.
- tcx.sess.delay_span_bug(
- span,
- format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
- );
- return Err(NoSolution);
- }
-
- constraints.outlives.extend(
- substs
- .as_generator()
- .upvar_tys()
- .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
- );
- constraints.outlives.push(substs.as_generator().resume_ty().into());
- }
-
- ty::Adt(def, substs) => {
- let DropckConstraint { dtorck_types, outlives, overflows } =
- tcx.at(span).adt_dtorck_constraint(def.did())?;
- // FIXME: we can try to recursively `dtorck_constraint_on_ty`
- // there, but that needs some way to handle cycles.
- constraints
- .dtorck_types
- .extend(dtorck_types.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
- constraints
- .outlives
- .extend(outlives.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
- constraints
- .overflows
- .extend(overflows.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
- }
-
- // Objects must be alive in order for their destructor
- // to be called.
- ty::Dynamic(..) => {
- constraints.outlives.push(ty.into());
- }
-
- // Types that can't be resolved. Pass them forward.
- ty::Alias(..) | ty::Param(..) => {
- constraints.dtorck_types.push(ty);
- }
-
- ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
- // By the time this code runs, all type variables ought to
- // be fully resolved.
- return Err(NoSolution);
- }
- }
-
- Ok(())
-}
-
/// Calculates the dtorck constraint for a type.
pub(crate) fn adt_dtorck_constraint(
tcx: TyCtxt<'_>,
@@ -311,7 +55,7 @@
let mut result = DropckConstraint::empty();
for field in def.all_fields() {
let fty = tcx.type_of(field.did).subst_identity();
- dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?;
+ dtorck_constraint_for_ty_inner(tcx, span, fty, 0, fty, &mut result)?;
}
result.outlives.extend(tcx.destructor_constraints(def));
dedup_dtorck_constraint(&mut result);
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 149dffc..f5b2753 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -1,5 +1,6 @@
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_span::source_map::DUMMY_SP;
use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
@@ -15,6 +16,7 @@
tcx: TyCtxt<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
+ assert!(!tcx.trait_solver_next());
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
// HACK This bubble is required for this tests to pass:
// impl-trait/issue99642.rs
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 0c2bb86..959838a 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -3,18 +3,13 @@
//! [`rustc_trait_selection::traits::query::type_op::implied_outlives_bounds`].
use rustc_infer::infer::canonical::{self, Canonical};
-use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::query::OutlivesBound;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::source_map::DUMMY_SP;
+use rustc_middle::ty::TyCtxt;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
-use rustc_trait_selection::traits::wf;
-use rustc_trait_selection::traits::ObligationCtxt;
-use smallvec::{smallvec, SmallVec};
+use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
pub(crate) fn provide(p: &mut Providers) {
*p = Providers { implied_outlives_bounds, ..*p };
@@ -29,164 +24,6 @@
> {
tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
let (param_env, ty) = key.into_parts();
- compute_implied_outlives_bounds(ocx, param_env, ty)
+ compute_implied_outlives_bounds_inner(ocx, param_env, ty)
})
}
-
-fn compute_implied_outlives_bounds<'tcx>(
- ocx: &ObligationCtxt<'_, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ty: Ty<'tcx>,
-) -> Fallible<Vec<OutlivesBound<'tcx>>> {
- let tcx = ocx.infcx.tcx;
-
- // Sometimes when we ask what it takes for T: WF, we get back that
- // U: WF is required; in that case, we push U onto this stack and
- // process it next. Because the resulting predicates aren't always
- // guaranteed to be a subset of the original type, so we need to store the
- // WF args we've computed in a set.
- let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
- let mut wf_args = vec![ty.into()];
-
- let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
- vec![];
-
- while let Some(arg) = wf_args.pop() {
- if !checked_wf_args.insert(arg) {
- continue;
- }
-
- // Compute the obligations for `arg` to be well-formed. If `arg` is
- // an unresolved inference variable, just substituted an empty set
- // -- because the return type here is going to be things we *add*
- // to the environment, it's always ok for this set to be smaller
- // than the ultimate set. (Note: normally there won't be
- // unresolved inference variables here anyway, but there might be
- // during typeck under some circumstances.)
- //
- // FIXME(@lcnr): It's not really "always fine", having fewer implied
- // bounds can be backward incompatible, e.g. #101951 was caused by
- // us not dealing with inference vars in `TypeOutlives` predicates.
- let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
- .unwrap_or_default();
-
- for obligation in obligations {
- debug!(?obligation);
- assert!(!obligation.has_escaping_bound_vars());
-
- // While these predicates should all be implied by other parts of
- // the program, they are still relevant as they may constrain
- // inference variables, which is necessary to add the correct
- // implied bounds in some cases, mostly when dealing with projections.
- //
- // Another important point here: we only register `Projection`
- // predicates, since otherwise we might register outlives
- // predicates containing inference variables, and we don't
- // learn anything new from those.
- if obligation.predicate.has_non_region_infer() {
- match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::AliasRelate(..) => {
- ocx.register_obligation(obligation.clone());
- }
- _ => {}
- }
- }
-
- let pred = match obligation.predicate.kind().no_bound_vars() {
- None => continue,
- Some(pred) => pred,
- };
- match pred {
- ty::PredicateKind::Clause(ty::Clause::Trait(..))
- // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
- // if we ever support that
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::Subtype(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::ConstEvaluatable(..)
- | ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::Ambiguous
- | ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
-
- // We need to search through *all* WellFormed predicates
- ty::PredicateKind::WellFormed(arg) => {
- wf_args.push(arg);
- }
-
- // We need to register region relationships
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
- r_a,
- r_b,
- ))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
-
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- ty_a,
- r_b,
- ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
- }
- }
- }
-
- // This call to `select_all_or_error` is necessary to constrain inference variables, which we
- // use further down when computing the implied bounds.
- match ocx.select_all_or_error().as_slice() {
- [] => (),
- _ => return Err(NoSolution),
- }
-
- // We lazily compute the outlives components as
- // `select_all_or_error` constrains inference variables.
- let implied_bounds = outlives_bounds
- .into_iter()
- .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
- ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
- ty::GenericArgKind::Type(ty_a) => {
- let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
- let mut components = smallvec![];
- push_outlives_components(tcx, ty_a, &mut components);
- implied_bounds_from_components(r_b, components)
- }
- ty::GenericArgKind::Const(_) => unreachable!(),
- })
- .collect();
-
- Ok(implied_bounds)
-}
-
-/// When we have an implied bound that `T: 'a`, we can further break
-/// this down to determine what relationships would have to hold for
-/// `T: 'a` to hold. We get to assume that the caller has validated
-/// those relationships.
-fn implied_bounds_from_components<'tcx>(
- sub_region: ty::Region<'tcx>,
- sup_components: SmallVec<[Component<'tcx>; 4]>,
-) -> Vec<OutlivesBound<'tcx>> {
- sup_components
- .into_iter()
- .filter_map(|component| {
- match component {
- Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
- Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
- Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
- Component::EscapingAlias(_) =>
- // If the projection has escaping regions, don't
- // try to infer any implied bounds even for its
- // free components. This is conservative, because
- // the caller will still have to prove that those
- // free components outlive `sub_region`. But the
- // idea is that the WAY that the caller proves
- // that may change in the future and we want to
- // give ourselves room to get smarter here.
- {
- None
- }
- Component::UnresolvedInferenceVariable(..) => None,
- }
- })
- .collect()
-}
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index b0f9c57..907e2d3 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -21,7 +21,8 @@
mod normalize_projection_ty;
mod type_op;
-pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
+pub use rustc_trait_selection::traits::query::type_op::ascribe_user_type::type_op_ascribe_user_type_with_span;
+pub use type_op::type_op_prove_predicate_with_cause;
use rustc_middle::query::Providers;
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 70dc7cce..9904acb 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,21 +1,19 @@
-use rustc_hir as hir;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCauseCode;
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{ParamEnvAnd, Predicate};
-use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
-use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
-use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType;
+use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
+ type_op_ascribe_user_type_with_span, AscribeUserType,
+};
use rustc_trait_selection::traits::query::type_op::eq::Eq;
use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
use std::fmt;
@@ -42,111 +40,6 @@
})
}
-/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
-/// this query can be re-run to better track the span of the obligation cause, and improve the error
-/// message. Do not call directly unless you're in that very specific context.
-pub fn type_op_ascribe_user_type_with_span<'tcx>(
- ocx: &ObligationCtxt<'_, 'tcx>,
- key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
- span: Option<Span>,
-) -> Result<(), NoSolution> {
- let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
- debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
- let span = span.unwrap_or(DUMMY_SP);
- match user_ty {
- UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
- UserType::TypeOf(def_id, user_substs) => {
- relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
- }
- };
- Ok(())
-}
-
-#[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_ty<'tcx>(
- ocx: &ObligationCtxt<'_, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- span: Span,
- mir_ty: Ty<'tcx>,
- user_ty: Ty<'tcx>,
-) -> Result<(), NoSolution> {
- let cause = ObligationCause::dummy_with_span(span);
- let user_ty = ocx.normalize(&cause, param_env, user_ty);
- ocx.eq(&cause, param_env, mir_ty, user_ty)?;
-
- // FIXME(#104764): We should check well-formedness before normalization.
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
- ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
- Ok(())
-}
-
-#[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_substs<'tcx>(
- ocx: &ObligationCtxt<'_, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- span: Span,
- mir_ty: Ty<'tcx>,
- def_id: hir::def_id::DefId,
- user_substs: UserSubsts<'tcx>,
-) -> Result<(), NoSolution> {
- let param_env = param_env.without_const();
- let UserSubsts { user_self_ty, substs } = user_substs;
- let tcx = ocx.infcx.tcx;
- let cause = ObligationCause::dummy_with_span(span);
-
- let ty = tcx.type_of(def_id).subst(tcx, substs);
- let ty = ocx.normalize(&cause, param_env, ty);
- debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
-
- ocx.eq(&cause, param_env, mir_ty, ty)?;
-
- // Prove the predicates coming along with `def_id`.
- //
- // Also, normalize the `instantiated_predicates`
- // because otherwise we wind up with duplicate "type
- // outlives" error messages.
- let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-
- debug!(?instantiated_predicates);
- for (instantiated_predicate, predicate_span) in instantiated_predicates {
- let span = if span == DUMMY_SP { predicate_span } else { span };
- let cause = ObligationCause::new(
- span,
- CRATE_DEF_ID,
- ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
- );
- let instantiated_predicate =
- ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
-
- ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
- }
-
- if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
- let self_ty = ocx.normalize(&cause, param_env, self_ty);
- let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
- let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
-
- ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
- ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
- }
-
- // In addition to proving the predicates, we have to
- // prove that `ty` is well-formed -- this is because
- // the WF of `ty` is predicated on the substs being
- // well-formed, and we haven't proven *that*. We don't
- // want to prove the WF of types from `substs` directly because they
- // haven't been normalized.
- //
- // FIXME(nmatsakis): Well, perhaps we should normalize
- // them? This would only be relevant if some input
- // type were ill-formed but did not appear in `ty`,
- // which...could happen with normalization...
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
- ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
- Ok(())
-}
-
fn type_op_eq<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
@@ -160,7 +53,7 @@
fn type_op_normalize<'tcx, T>(
ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, Normalize<T>>,
-) -> Fallible<T>
+) -> Result<T, NoSolution>
where
T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
{
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index 5bc3e3c..c416aa5 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -1,61 +1,31 @@
-ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
+
+ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
+
+ty_utils_array_not_supported = array construction is not supported in generic constants
+
+ty_utils_assign_not_supported = assignment is not supported in generic constants
+
+ty_utils_binary_not_supported = unsupported binary operation in generic constants
+
+ty_utils_block_not_supported = blocks are not supported in generic constants
+
+ty_utils_borrow_not_supported = borrowing is not supported in generic constants
+
+ty_utils_box_not_supported = allocations are not allowed in generic constants
+
+ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
+
+ty_utils_const_block_not_supported = const blocks are not supported in generic constants
+
+ty_utils_control_flow_not_supported = control flow is not supported in generic constants
+
+ty_utils_field_not_supported = field access is not supported in generic constants
ty_utils_generic_constant_too_complex = overly complex generic constant
.help = consider moving this anonymous constant into a `const` function
.maybe_supported = this operation may be supported in the future
-ty_utils_borrow_not_supported = borrowing is not supported in generic constants
-
-ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
-
-ty_utils_array_not_supported = array construction is not supported in generic constants
-
-ty_utils_block_not_supported = blocks are not supported in generic constants
-
-ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
-
-ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
-
-ty_utils_index_not_supported = indexing is not supported in generic constants
-
-ty_utils_field_not_supported = field access is not supported in generic constants
-
-ty_utils_const_block_not_supported = const blocks are not supported in generic constants
-
-ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
-
-ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
-
-ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
-
-ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
-
-ty_utils_box_not_supported = allocations are not allowed in generic constants
-
-ty_utils_binary_not_supported = unsupported binary operation in generic constants
-
-ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
-
-ty_utils_assign_not_supported = assignment is not supported in generic constants
-
-ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
-
-ty_utils_control_flow_not_supported = control flow is not supported in generic constants
-
-ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
-
-ty_utils_operation_not_supported = unsupported operation in generic constants
-
-ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
-
-ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
-
-ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
-
-ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
-
-ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
-
ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
.label = generic argument `{$arg}` used twice
.note = for this opaque type
@@ -63,3 +33,33 @@
ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
.label = argument `{$arg}` is not a generic parameter
.note = for this opaque type
+
+ty_utils_index_not_supported = indexing is not supported in generic constants
+
+ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
+
+ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
+
+ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
+
+ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
+
+ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
+
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+
+ty_utils_operation_not_supported = unsupported operation in generic constants
+
+ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
+
+ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
+
+ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
+
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
+
+ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+
+ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 6f2ba95..01d1fdc 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -37,6 +37,9 @@
#[rustc_allocator_zeroed]
#[rustc_nounwind]
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
+
+ #[cfg(not(bootstrap))]
+ static __rust_no_alloc_shim_is_unstable: u8;
}
/// The global memory allocator.
@@ -90,7 +93,14 @@
#[must_use = "losing the pointer will leak memory"]
#[inline]
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
- unsafe { __rust_alloc(layout.size(), layout.align()) }
+ unsafe {
+ // Make sure we don't accidentally allow omitting the allocator shim in
+ // stable code until it is actually stabilized.
+ #[cfg(not(bootstrap))]
+ core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
+
+ __rust_alloc(layout.size(), layout.align())
+ }
}
/// Deallocate memory with the global allocator.
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index d1c1ae6..7969f40 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -662,12 +662,20 @@
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
/// noting that the hashes and ordering will vary between Rust releases. Beware
/// of relying on them inside of your code!
-#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialOrd, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
t: u64,
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for TypeId {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.t == other.t
+ }
+}
+
impl TypeId {
/// Returns the `TypeId` of the type this generic function has been
/// instantiated with.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index bdb4c97..e3885d4 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -204,6 +204,7 @@
{
type Error = TryFromSliceError;
+ #[inline]
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
<&Self>::try_from(slice).map(|r| *r)
}
@@ -228,6 +229,7 @@
{
type Error = TryFromSliceError;
+ #[inline]
fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
<Self>::try_from(&*slice)
}
@@ -249,6 +251,7 @@
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
type Error = TryFromSliceError;
+ #[inline]
fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_ptr() as *const [T; N];
@@ -276,6 +279,7 @@
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
type Error = TryFromSliceError;
+ #[inline]
fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_mut_ptr() as *mut [T; N];
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index b24882d..c4134db 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1427,7 +1427,7 @@
#[rustc_builtin_macro]
#[macro_export]
#[rustc_diagnostic_item = "assert_macro"]
- #[allow_internal_unstable(core_panic, edition_panic)]
+ #[allow_internal_unstable(core_panic, edition_panic, generic_assert_internals)]
macro_rules! assert {
($cond:expr $(,)?) => {{ /* compiler built-in */ }};
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5ece1b7..1f19555 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -42,6 +42,7 @@
mod iter;
mod raw;
mod rotate;
+mod select;
mod specialize;
#[unstable(feature = "str_internals", issue = "none")]
@@ -319,6 +320,264 @@
if let [.., last] = self { Some(last) } else { None }
}
+ /// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let u = [10, 40, 30];
+ /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
+ ///
+ /// let v: &[i32] = &[10];
+ /// assert_eq!(None, v.first_chunk::<2>());
+ ///
+ /// let w: &[i32] = &[];
+ /// assert_eq!(Some(&[]), w.first_chunk::<0>());
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We explicitly check for the correct number of elements,
+ // and do not let the reference outlive the slice.
+ Some(unsafe { &*(self.as_ptr() as *const [T; N]) })
+ }
+ }
+
+ /// Returns a mutable reference to the first `N` elements of the slice,
+ /// or `None` if it has fewer than `N` elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &mut [0, 1, 2];
+ ///
+ /// if let Some(first) = x.first_chunk_mut::<2>() {
+ /// first[0] = 5;
+ /// first[1] = 4;
+ /// }
+ /// assert_eq!(x, &[5, 4, 2]);
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We explicitly check for the correct number of elements,
+ // do not let the reference outlive the slice,
+ // and require exclusive access to the entire slice to mutate the chunk.
+ Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) })
+ }
+ }
+
+ /// Returns the first `N` elements of the slice and the remainder,
+ /// or `None` if it has fewer than `N` elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &[0, 1, 2];
+ ///
+ /// if let Some((first, elements)) = x.split_first_chunk::<2>() {
+ /// assert_eq!(first, &[0, 1]);
+ /// assert_eq!(elements, &[2]);
+ /// }
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the split.
+ let (first, tail) = unsafe { self.split_at_unchecked(N) };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // and do not let the references outlive the slice.
+ Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail))
+ }
+ }
+
+ /// Returns a mutable reference to the first `N` elements of the slice and the remainder,
+ /// or `None` if it has fewer than `N` elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &mut [0, 1, 2];
+ ///
+ /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
+ /// first[0] = 3;
+ /// first[1] = 4;
+ /// elements[0] = 5;
+ /// }
+ /// assert_eq!(x, &[3, 4, 5]);
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn split_first_chunk_mut<const N: usize>(
+ &mut self,
+ ) -> Option<(&mut [T; N], &mut [T])> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the split.
+ let (first, tail) = unsafe { self.split_at_mut_unchecked(N) };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // do not let the reference outlive the slice,
+ // and enforce exclusive mutability of the chunk by the split.
+ Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail))
+ }
+ }
+
+ /// Returns the last `N` elements of the slice and the remainder,
+ /// or `None` if it has fewer than `N` elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &[0, 1, 2];
+ ///
+ /// if let Some((last, elements)) = x.split_last_chunk::<2>() {
+ /// assert_eq!(last, &[1, 2]);
+ /// assert_eq!(elements, &[0]);
+ /// }
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the split.
+ let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // and do not let the references outlive the slice.
+ Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init))
+ }
+ }
+
+ /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &mut [0, 1, 2];
+ ///
+ /// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() {
+ /// last[0] = 3;
+ /// last[1] = 4;
+ /// elements[0] = 5;
+ /// }
+ /// assert_eq!(x, &[5, 3, 4]);
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn split_last_chunk_mut<const N: usize>(
+ &mut self,
+ ) -> Option<(&mut [T; N], &mut [T])> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the split.
+ let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // do not let the reference outlive the slice,
+ // and enforce exclusive mutability of the chunk by the split.
+ Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init))
+ }
+ }
+
+ /// Returns the last element of the slice, or `None` if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let u = [10, 40, 30];
+ /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
+ ///
+ /// let v: &[i32] = &[10];
+ /// assert_eq!(None, v.last_chunk::<2>());
+ ///
+ /// let w: &[i32] = &[];
+ /// assert_eq!(Some(&[]), w.last_chunk::<0>());
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the slice.
+ // FIXME: Without const traits, we need this instead of `get_unchecked`.
+ let last = unsafe { self.split_at_unchecked(self.len() - N).1 };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // and do not let the references outlive the slice.
+ Some(unsafe { &*(last.as_ptr() as *const [T; N]) })
+ }
+ }
+
+ /// Returns a mutable pointer to the last item in the slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_first_last_chunk)]
+ ///
+ /// let x = &mut [0, 1, 2];
+ ///
+ /// if let Some(last) = x.last_chunk_mut::<2>() {
+ /// last[0] = 10;
+ /// last[1] = 20;
+ /// }
+ /// assert_eq!(x, &[0, 10, 20]);
+ /// ```
+ #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+ #[inline]
+ pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
+ if self.len() < N {
+ None
+ } else {
+ // SAFETY: We manually verified the bounds of the slice.
+ // FIXME: Without const traits, we need this instead of `get_unchecked`.
+ let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 };
+
+ // SAFETY: We explicitly check for the correct number of elements,
+ // do not let the reference outlive the slice,
+ // and require exclusive access to the entire slice to mutate the chunk.
+ Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })
+ }
+ }
+
/// Returns a reference to an element or subslice depending on the type of
/// index.
///
@@ -2746,8 +3005,9 @@
///
/// # Current implementation
///
- /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
- /// used for [`sort_unstable`].
+ /// The current algorithm is an introselect implementation based on Pattern Defeating Quicksort, which is also
+ /// the basis for [`sort_unstable`]. The fallback algorithm is Median of Medians using Tukey's Ninther for
+ /// pivot selection, which guarantees linear runtime for all inputs.
///
/// [`sort_unstable`]: slice::sort_unstable
///
@@ -2776,7 +3036,7 @@
where
T: Ord,
{
- sort::partition_at_index(self, index, T::lt)
+ select::partition_at_index(self, index, T::lt)
}
/// Reorder the slice with a comparator function such that the element at `index` is at its
@@ -2797,8 +3057,9 @@
///
/// # Current implementation
///
- /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
- /// used for [`sort_unstable`].
+ /// The current algorithm is an introselect implementation based on Pattern Defeating Quicksort, which is also
+ /// the basis for [`sort_unstable`]. The fallback algorithm is Median of Medians using Tukey's Ninther for
+ /// pivot selection, which guarantees linear runtime for all inputs.
///
/// [`sort_unstable`]: slice::sort_unstable
///
@@ -2831,7 +3092,7 @@
where
F: FnMut(&T, &T) -> Ordering,
{
- sort::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
+ select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
}
/// Reorder the slice with a key extraction function such that the element at `index` is at its
@@ -2887,7 +3148,7 @@
F: FnMut(&T) -> K,
K: Ord,
{
- sort::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
+ select::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
}
/// Moves all consecutive repeated elements to the end of the slice according to the
diff --git a/library/core/src/slice/select.rs b/library/core/src/slice/select.rs
new file mode 100644
index 0000000..ffc1935
--- /dev/null
+++ b/library/core/src/slice/select.rs
@@ -0,0 +1,302 @@
+//! Slice selection
+//!
+//! This module contains the implementation for `slice::select_nth_unstable`.
+//! It uses an introselect algorithm based on Orson Peters' pattern-defeating quicksort,
+//! published at: <https://github.com/orlp/pdqsort>
+//!
+//! The fallback algorithm used for introselect is Median of Medians using Tukey's Ninther
+//! for pivot selection. Using this as a fallback ensures O(n) worst case running time with
+//! better performance than one would get using heapsort as fallback.
+
+use crate::cmp;
+use crate::mem::{self, SizedTypeProperties};
+use crate::slice::sort::{
+ break_patterns, choose_pivot, insertion_sort_shift_left, partition, partition_equal,
+};
+
+// For slices of up to this length it's probably faster to simply sort them.
+// Defined at the module scope because it's used in multiple functions.
+const MAX_INSERTION: usize = 10;
+
+fn partition_at_index_loop<'a, T, F>(
+ mut v: &'a mut [T],
+ mut index: usize,
+ is_less: &mut F,
+ mut pred: Option<&'a T>,
+) where
+ F: FnMut(&T, &T) -> bool,
+{
+ // Limit the amount of iterations and fall back to fast deterministic selection
+ // to ensure O(n) worst case running time. This limit needs to be constant, because
+ // using `ilog2(len)` like in `sort` would result in O(n log n) time complexity.
+ // The exact value of the limit is chosen somewhat arbitrarily, but for most inputs bad pivot
+ // selections should be relatively rare, so the limit usually shouldn't be reached
+ // anyways.
+ let mut limit = 16;
+
+ // True if the last partitioning was reasonably balanced.
+ let mut was_balanced = true;
+
+ loop {
+ if v.len() <= MAX_INSERTION {
+ if v.len() > 1 {
+ insertion_sort_shift_left(v, 1, is_less);
+ }
+ return;
+ }
+
+ if limit == 0 {
+ median_of_medians(v, is_less, index);
+ return;
+ }
+
+ // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
+ // some elements around. Hopefully we'll choose a better pivot this time.
+ if !was_balanced {
+ break_patterns(v);
+ limit -= 1;
+ }
+
+ // Choose a pivot
+ let (pivot, _) = choose_pivot(v, is_less);
+
+ // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
+ // slice. Partition the slice into elements equal to and elements greater than the pivot.
+ // This case is usually hit when the slice contains many duplicate elements.
+ if let Some(p) = pred {
+ if !is_less(p, &v[pivot]) {
+ let mid = partition_equal(v, pivot, is_less);
+
+ // If we've passed our index, then we're good.
+ if mid > index {
+ return;
+ }
+
+ // Otherwise, continue sorting elements greater than the pivot.
+ v = &mut v[mid..];
+ index = index - mid;
+ pred = None;
+ continue;
+ }
+ }
+
+ let (mid, _) = partition(v, pivot, is_less);
+ was_balanced = cmp::min(mid, v.len() - mid) >= v.len() / 8;
+
+ // Split the slice into `left`, `pivot`, and `right`.
+ let (left, right) = v.split_at_mut(mid);
+ let (pivot, right) = right.split_at_mut(1);
+ let pivot = &pivot[0];
+
+ if mid < index {
+ v = right;
+ index = index - mid - 1;
+ pred = Some(pivot);
+ } else if mid > index {
+ v = left;
+ } else {
+ // If mid == index, then we're done, since partition() guaranteed that all elements
+ // after mid are greater than or equal to mid.
+ return;
+ }
+ }
+}
+
+/// Helper function that returns the index of the minimum element in the slice using the given
+/// comparator function
+fn min_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
+ slice
+ .iter()
+ .enumerate()
+ .reduce(|acc, t| if is_less(t.1, acc.1) { t } else { acc })
+ .map(|(i, _)| i)
+}
+
+/// Helper function that returns the index of the maximum element in the slice using the given
+/// comparator function
+fn max_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
+ slice
+ .iter()
+ .enumerate()
+ .reduce(|acc, t| if is_less(acc.1, t.1) { t } else { acc })
+ .map(|(i, _)| i)
+}
+
+/// Reorder the slice such that the element at `index` is at its final sorted position.
+pub fn partition_at_index<T, F>(
+ v: &mut [T],
+ index: usize,
+ mut is_less: F,
+) -> (&mut [T], &mut T, &mut [T])
+where
+ F: FnMut(&T, &T) -> bool,
+{
+ if index >= v.len() {
+ panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
+ }
+
+ if T::IS_ZST {
+ // Sorting has no meaningful behavior on zero-sized types. Do nothing.
+ } else if index == v.len() - 1 {
+ // Find max element and place it in the last position of the array. We're free to use
+ // `unwrap()` here because we know v must not be empty.
+ let max_idx = max_index(v, &mut is_less).unwrap();
+ v.swap(max_idx, index);
+ } else if index == 0 {
+ // Find min element and place it in the first position of the array. We're free to use
+ // `unwrap()` here because we know v must not be empty.
+ let min_idx = min_index(v, &mut is_less).unwrap();
+ v.swap(min_idx, index);
+ } else {
+ partition_at_index_loop(v, index, &mut is_less, None);
+ }
+
+ let (left, right) = v.split_at_mut(index);
+ let (pivot, right) = right.split_at_mut(1);
+ let pivot = &mut pivot[0];
+ (left, pivot, right)
+}
+
+/// Selection algorithm to select the k-th element from the slice in guaranteed O(n) time.
+/// This is essentially a quickselect that uses Tukey's Ninther for pivot selection
+fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut F, mut k: usize) {
+ // Since this function isn't public, it should never be called with an out-of-bounds index.
+ debug_assert!(k < v.len());
+
+ // If T is as ZST, `partition_at_index` will already return early.
+ debug_assert!(!T::IS_ZST);
+
+ // We now know that `k < v.len() <= isize::MAX`
+ loop {
+ if v.len() <= MAX_INSERTION {
+ if v.len() > 1 {
+ insertion_sort_shift_left(v, 1, is_less);
+ }
+ return;
+ }
+
+ // `median_of_{minima,maxima}` can't handle the extreme cases of the first/last element,
+ // so we catch them here and just do a linear search.
+ if k == v.len() - 1 {
+ // Find max element and place it in the last position of the array. We're free to use
+ // `unwrap()` here because we know v must not be empty.
+ let max_idx = max_index(v, is_less).unwrap();
+ v.swap(max_idx, k);
+ return;
+ } else if k == 0 {
+ // Find min element and place it in the first position of the array. We're free to use
+ // `unwrap()` here because we know v must not be empty.
+ let min_idx = min_index(v, is_less).unwrap();
+ v.swap(min_idx, k);
+ return;
+ }
+
+ let p = median_of_ninthers(v, is_less);
+
+ if p == k {
+ return;
+ } else if p > k {
+ v = &mut v[..p];
+ } else {
+ // Since `p < k < v.len()`, `p + 1` doesn't overflow and is
+ // a valid index into the slice.
+ v = &mut v[p + 1..];
+ k -= p + 1;
+ }
+ }
+}
+
+// Optimized for when `k` lies somewhere in the middle of the slice. Selects a pivot
+// as close as possible to the median of the slice. For more details on how the algorithm
+// operates, refer to the paper <https://drops.dagstuhl.de/opus/volltexte/2017/7612/pdf/LIPIcs-SEA-2017-24.pdf>.
+fn median_of_ninthers<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) -> usize {
+ // use `saturating_mul` so the multiplication doesn't overflow on 16-bit platforms.
+ let frac = if v.len() <= 1024 {
+ v.len() / 12
+ } else if v.len() <= 128_usize.saturating_mul(1024) {
+ v.len() / 64
+ } else {
+ v.len() / 1024
+ };
+
+ let pivot = frac / 2;
+ let lo = v.len() / 2 - pivot;
+ let hi = frac + lo;
+ let gap = (v.len() - 9 * frac) / 4;
+ let mut a = lo - 4 * frac - gap;
+ let mut b = hi + gap;
+ for i in lo..hi {
+ ninther(v, is_less, a, i - frac, b, a + 1, i, b + 1, a + 2, i + frac, b + 2);
+ a += 3;
+ b += 3;
+ }
+
+ median_of_medians(&mut v[lo..lo + frac], is_less, pivot);
+ partition(v, lo + pivot, is_less).0
+}
+
+/// Moves around the 9 elements at the indices a..i, such that
+/// `v[d]` contains the median of the 9 elements and the other
+/// elements are partitioned around it.
+fn ninther<T, F: FnMut(&T, &T) -> bool>(
+ v: &mut [T],
+ is_less: &mut F,
+ a: usize,
+ mut b: usize,
+ c: usize,
+ mut d: usize,
+ e: usize,
+ mut f: usize,
+ g: usize,
+ mut h: usize,
+ i: usize,
+) {
+ b = median_idx(v, is_less, a, b, c);
+ h = median_idx(v, is_less, g, h, i);
+ if is_less(&v[h], &v[b]) {
+ mem::swap(&mut b, &mut h);
+ }
+ if is_less(&v[f], &v[d]) {
+ mem::swap(&mut d, &mut f);
+ }
+ if is_less(&v[e], &v[d]) {
+ // do nothing
+ } else if is_less(&v[f], &v[e]) {
+ d = f;
+ } else {
+ if is_less(&v[e], &v[b]) {
+ v.swap(e, b);
+ } else if is_less(&v[h], &v[e]) {
+ v.swap(e, h);
+ }
+ return;
+ }
+ if is_less(&v[d], &v[b]) {
+ d = b;
+ } else if is_less(&v[h], &v[d]) {
+ d = h;
+ }
+
+ v.swap(d, e);
+}
+
+/// returns the index pointing to the median of the 3
+/// elements `v[a]`, `v[b]` and `v[c]`
+fn median_idx<T, F: FnMut(&T, &T) -> bool>(
+ v: &[T],
+ is_less: &mut F,
+ mut a: usize,
+ b: usize,
+ mut c: usize,
+) -> usize {
+ if is_less(&v[c], &v[a]) {
+ mem::swap(&mut a, &mut c);
+ }
+ if is_less(&v[c], &v[b]) {
+ return c;
+ }
+ if is_less(&v[b], &v[a]) {
+ return a;
+ }
+ b
+}
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index eb8595c..db76d26 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -145,7 +145,7 @@
/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no
/// performance impact. Even improving performance in some cases.
#[inline(never)]
-fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
+pub(super) fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
@@ -557,7 +557,7 @@
///
/// 1. Number of elements smaller than `v[pivot]`.
/// 2. True if `v` was already partitioned.
-fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
+pub(super) fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
@@ -612,7 +612,7 @@
///
/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
/// elements smaller than the pivot.
-fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
+pub(super) fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
where
F: FnMut(&T, &T) -> bool,
{
@@ -670,7 +670,7 @@
/// Scatters some elements around in an attempt to break patterns that might cause imbalanced
/// partitions in quicksort.
#[cold]
-fn break_patterns<T>(v: &mut [T]) {
+pub(super) fn break_patterns<T>(v: &mut [T]) {
let len = v.len();
if len >= 8 {
let mut seed = len;
@@ -719,7 +719,7 @@
/// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted.
///
/// Elements in `v` might be reordered in the process.
-fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
+pub(super) fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
@@ -897,138 +897,6 @@
recurse(v, &mut is_less, None, limit);
}
-fn partition_at_index_loop<'a, T, F>(
- mut v: &'a mut [T],
- mut index: usize,
- is_less: &mut F,
- mut pred: Option<&'a T>,
-) where
- F: FnMut(&T, &T) -> bool,
-{
- // Limit the amount of iterations and fall back to heapsort, similarly to `slice::sort_unstable`.
- // This lowers the worst case running time from O(n^2) to O(n log n).
- // FIXME: Investigate whether it would be better to use something like Median of Medians
- // or Fast Deterministic Selection to guarantee O(n) worst case.
- let mut limit = usize::BITS - v.len().leading_zeros();
-
- // True if the last partitioning was reasonably balanced.
- let mut was_balanced = true;
-
- loop {
- let len = v.len();
-
- // For slices of up to this length it's probably faster to simply sort them.
- const MAX_INSERTION: usize = 10;
- if len <= MAX_INSERTION {
- if len >= 2 {
- insertion_sort_shift_left(v, 1, is_less);
- }
- return;
- }
-
- if limit == 0 {
- heapsort(v, is_less);
- return;
- }
-
- // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
- // some elements around. Hopefully we'll choose a better pivot this time.
- if !was_balanced {
- break_patterns(v);
- limit -= 1;
- }
-
- // Choose a pivot
- let (pivot, _) = choose_pivot(v, is_less);
-
- // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
- // slice. Partition the slice into elements equal to and elements greater than the pivot.
- // This case is usually hit when the slice contains many duplicate elements.
- if let Some(p) = pred {
- if !is_less(p, &v[pivot]) {
- let mid = partition_equal(v, pivot, is_less);
-
- // If we've passed our index, then we're good.
- if mid > index {
- return;
- }
-
- // Otherwise, continue sorting elements greater than the pivot.
- v = &mut v[mid..];
- index = index - mid;
- pred = None;
- continue;
- }
- }
-
- let (mid, _) = partition(v, pivot, is_less);
- was_balanced = cmp::min(mid, len - mid) >= len / 8;
-
- // Split the slice into `left`, `pivot`, and `right`.
- let (left, right) = v.split_at_mut(mid);
- let (pivot, right) = right.split_at_mut(1);
- let pivot = &pivot[0];
-
- if mid < index {
- v = right;
- index = index - mid - 1;
- pred = Some(pivot);
- } else if mid > index {
- v = left;
- } else {
- // If mid == index, then we're done, since partition() guaranteed that all elements
- // after mid are greater than or equal to mid.
- return;
- }
- }
-}
-
-/// Reorder the slice such that the element at `index` is at its final sorted position.
-pub fn partition_at_index<T, F>(
- v: &mut [T],
- index: usize,
- mut is_less: F,
-) -> (&mut [T], &mut T, &mut [T])
-where
- F: FnMut(&T, &T) -> bool,
-{
- use cmp::Ordering::Greater;
- use cmp::Ordering::Less;
-
- if index >= v.len() {
- panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
- }
-
- if T::IS_ZST {
- // Sorting has no meaningful behavior on zero-sized types. Do nothing.
- } else if index == v.len() - 1 {
- // Find max element and place it in the last position of the array. We're free to use
- // `unwrap()` here because we know v must not be empty.
- let (max_index, _) = v
- .iter()
- .enumerate()
- .max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
- .unwrap();
- v.swap(max_index, index);
- } else if index == 0 {
- // Find min element and place it in the first position of the array. We're free to use
- // `unwrap()` here because we know v must not be empty.
- let (min_index, _) = v
- .iter()
- .enumerate()
- .min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
- .unwrap();
- v.swap(min_index, index);
- } else {
- partition_at_index_loop(v, index, &mut is_less, None);
- }
-
- let (left, right) = v.split_at_mut(index);
- let (pivot, right) = right.split_at_mut(1);
- let pivot = &mut pivot[0];
- (left, pivot, right)
-}
-
/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and
/// stores the result into `v[..]`.
///
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 1454b00..824abc7 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.91" }
+compiler_builtins = { version = "0.1.92" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.13", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9e09ce3..8a007d0 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -593,7 +593,8 @@
/// This may happen for example because fewer bytes are actually available right now
/// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
///
- /// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
+ /// As this trait is safe to implement, callers in unsafe code cannot rely on
+ /// `n <= buf.len()` for safety.
/// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
/// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
/// `n > buf.len()`.
@@ -603,8 +604,8 @@
/// contents of `buf` being true. It is recommended that *implementations*
/// only write data to `buf` instead of reading its contents.
///
- /// Correspondingly, however, *callers* of this method must not assume any guarantees
- /// about how the implementation uses `buf`. The trait is safe to implement,
+ /// Correspondingly, however, *callers* of this method in unsafe code must not assume
+ /// any guarantees about how the implementation uses `buf`. The trait is safe to implement,
/// so it is possible that the code that's supposed to write to the buffer might also read
/// from it. It is your responsibility to make sure that `buf` is initialized
/// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index 9d22ebb..6ac3b3e 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -404,13 +404,13 @@
Some("terse") => OutputFormat::Terse,
Some("json") => {
if !allow_unstable {
- return Err("The \"json\" format is only accepted on the nightly compiler".into());
+ return Err("The \"json\" format is only accepted on the nightly compiler with -Z unstable-options".into());
}
OutputFormat::Json
}
Some("junit") => {
if !allow_unstable {
- return Err("The \"junit\" format is only accepted on the nightly compiler".into());
+ return Err("The \"junit\" format is only accepted on the nightly compiler with -Z unstable-options".into());
}
OutputFormat::Junit
}
diff --git a/library/test/src/options.rs b/library/test/src/options.rs
index 75ec0b6..3eaad59 100644
--- a/library/test/src/options.rs
+++ b/library/test/src/options.rs
@@ -16,19 +16,21 @@
}
/// Whether should console output be colored or not
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Default, Debug)]
pub enum ColorConfig {
+ #[default]
AutoColor,
AlwaysColor,
NeverColor,
}
/// Format of the test results output
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum OutputFormat {
/// Verbose output
Pretty,
/// Quiet output
+ #[default]
Terse,
/// JSON output
Json,
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 50ace98..58d1926 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -226,16 +226,13 @@
def default_build_triple(verbose):
"""Build triple as in LLVM"""
- # If the user already has a host build triple with an existing `rustc`
- # install, use their preference. This fixes most issues with Windows builds
- # being detected as GNU instead of MSVC.
+ # If we're on Windows and have an existing `rustc` toolchain, use `rustc --version --verbose`
+ # to find our host target triple. This fixes an issue with Windows builds being detected
+ # as GNU instead of MSVC.
+ # Otherwise, detect it via `uname`
default_encoding = sys.getdefaultencoding()
- if sys.platform == 'darwin':
- if verbose:
- print("not using rustc detection as it is unreliable on macOS", file=sys.stderr)
- print("falling back to auto-detect", file=sys.stderr)
- else:
+ if platform_is_win32():
try:
version = subprocess.check_output(["rustc", "--version", "--verbose"],
stderr=subprocess.DEVNULL)
@@ -253,19 +250,17 @@
print("falling back to auto-detect", file=sys.stderr)
required = not platform_is_win32()
- ostype = require(["uname", "-s"], exit=required)
- cputype = require(['uname', '-m'], exit=required)
+ uname = require(["uname", "-smp"], exit=required)
# If we do not have `uname`, assume Windows.
- if ostype is None or cputype is None:
+ if uname is None:
return 'x86_64-pc-windows-msvc'
- ostype = ostype.decode(default_encoding)
- cputype = cputype.decode(default_encoding)
+ kernel, cputype, processor = uname.decode(default_encoding).split()
# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
- ostype_mapper = {
+ kerneltype_mapper = {
'Darwin': 'apple-darwin',
'DragonFly': 'unknown-dragonfly',
'FreeBSD': 'unknown-freebsd',
@@ -275,17 +270,18 @@
}
# Consider the direct transformation first and then the special cases
- if ostype in ostype_mapper:
- ostype = ostype_mapper[ostype]
- elif ostype == 'Linux':
- os_from_sp = subprocess.check_output(
- ['uname', '-o']).strip().decode(default_encoding)
- if os_from_sp == 'Android':
- ostype = 'linux-android'
+ if kernel in kerneltype_mapper:
+ kernel = kerneltype_mapper[kernel]
+ elif kernel == 'Linux':
+ # Apple doesn't support `-o` so this can't be used in the combined
+ # uname invocation above
+ ostype = require(["uname", "-o"], exit=required).decode(default_encoding)
+ if ostype == 'Android':
+ kernel = 'linux-android'
else:
- ostype = 'unknown-linux-gnu'
- elif ostype == 'SunOS':
- ostype = 'pc-solaris'
+ kernel = 'unknown-linux-gnu'
+ elif kernel == 'SunOS':
+ kernel = 'pc-solaris'
# On Solaris, uname -m will return a machine classification instead
# of a cpu type, so uname -p is recommended instead. However, the
# output from that option is too generic for our purposes (it will
@@ -294,34 +290,34 @@
cputype = require(['isainfo', '-k']).decode(default_encoding)
# sparc cpus have sun as a target vendor
if 'sparc' in cputype:
- ostype = 'sun-solaris'
- elif ostype.startswith('MINGW'):
+ kernel = 'sun-solaris'
+ elif kernel.startswith('MINGW'):
# msys' `uname` does not print gcc configuration, but prints msys
# configuration. so we cannot believe `uname -m`:
# msys1 is always i686 and msys2 is always x86_64.
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and
# MINGW64 on x86_64.
- ostype = 'pc-windows-gnu'
+ kernel = 'pc-windows-gnu'
cputype = 'i686'
if os.environ.get('MSYSTEM') == 'MINGW64':
cputype = 'x86_64'
- elif ostype.startswith('MSYS'):
- ostype = 'pc-windows-gnu'
- elif ostype.startswith('CYGWIN_NT'):
+ elif kernel.startswith('MSYS'):
+ kernel = 'pc-windows-gnu'
+ elif kernel.startswith('CYGWIN_NT'):
cputype = 'i686'
- if ostype.endswith('WOW64'):
+ if kernel.endswith('WOW64'):
cputype = 'x86_64'
- ostype = 'pc-windows-gnu'
- elif sys.platform == 'win32':
+ kernel = 'pc-windows-gnu'
+ elif platform_is_win32():
# Some Windows platforms might have a `uname` command that returns a
# non-standard string (e.g. gnuwin32 tools returns `windows32`). In
# these cases, fall back to using sys.platform.
return 'x86_64-pc-windows-msvc'
else:
- err = "unknown OS type: {}".format(ostype)
+ err = "unknown OS type: {}".format(kernel)
sys.exit(err)
- if cputype in ['powerpc', 'riscv'] and ostype == 'unknown-freebsd':
+ if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd':
cputype = subprocess.check_output(
['uname', '-p']).strip().decode(default_encoding)
cputype_mapper = {
@@ -354,24 +350,23 @@
cputype = cputype_mapper[cputype]
elif cputype in {'xscale', 'arm'}:
cputype = 'arm'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
- elif ostype == 'unknown-freebsd':
- cputype = subprocess.check_output(
- ['uname', '-p']).strip().decode(default_encoding)
- ostype = 'unknown-freebsd'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
+ elif kernel == 'unknown-freebsd':
+ cputype = processor
+ kernel = 'unknown-freebsd'
elif cputype == 'armv6l':
cputype = 'arm'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
else:
- ostype += 'eabihf'
+ kernel += 'eabihf'
elif cputype in {'armv7l', 'armv8l'}:
cputype = 'armv7'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
else:
- ostype += 'eabihf'
+ kernel += 'eabihf'
elif cputype == 'mips':
if sys.byteorder == 'big':
cputype = 'mips'
@@ -387,14 +382,14 @@
else:
raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
# only the n64 ABI is supported, indicate it
- ostype += 'abi64'
+ kernel += 'abi64'
elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
pass
else:
err = "unknown cpu type: {}".format(cputype)
sys.exit(err)
- return "{}-{}".format(cputype, ostype)
+ return "{}-{}".format(cputype, kernel)
@contextlib.contextmanager
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index cf7c659..2fa4455 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -264,7 +264,7 @@
/// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path.
///
- /// This can be used with [`ShouldRun::krate`], [`ShouldRun::path`], or [`ShouldRun::alias`].
+ /// This can be used with [`ShouldRun::crate_or_deps`], [`ShouldRun::path`], or [`ShouldRun::alias`].
#[track_caller]
pub fn assert_single_path(&self) -> &TaskPath {
match self {
@@ -689,7 +689,8 @@
tool::Miri,
tool::CargoMiri,
llvm::Lld,
- llvm::CrtBeginEnd
+ llvm::CrtBeginEnd,
+ tool::RustdocGUITest,
),
Kind::Check | Kind::Clippy | Kind::Fix => describe!(
check::Std,
@@ -787,6 +788,7 @@
doc::EditionGuide,
doc::StyleGuide,
doc::Tidy,
+ doc::Bootstrap,
),
Kind::Dist => describe!(
dist::Docs,
@@ -1915,10 +1917,10 @@
}
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
- // This replaces spaces with newlines because RUSTDOCFLAGS does not
+ // This replaces spaces with tabs because RUSTDOCFLAGS does not
// support arguments with regular spaces. Hopefully someday Cargo will
// have space support.
- let rust_version = self.rust_version().replace(' ', "\n");
+ let rust_version = self.rust_version().replace(' ', "\t");
rustdocflags.arg("--crate-version").arg(&rust_version);
// Environment variables *required* throughout the build
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 710c8b5..e192cda 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -350,7 +350,7 @@
}
/// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone, PartialEq)]
+#[derive(Default, Clone, PartialEq, Debug)]
pub enum RustcLto {
Off,
#[default]
@@ -508,29 +508,42 @@
profile: Option<String>,
}
+/// Describes how to handle conflicts in merging two [`TomlConfig`]
+#[derive(Copy, Clone, Debug)]
+enum ReplaceOpt {
+ /// Silently ignore a duplicated value
+ IgnoreDuplicate,
+ /// Override the current value, even if it's `Some`
+ Override,
+ /// Exit with an error on duplicate values
+ ErrorOnDuplicate,
+}
+
trait Merge {
- fn merge(&mut self, other: Self);
+ fn merge(&mut self, other: Self, replace: ReplaceOpt);
}
impl Merge for TomlConfig {
fn merge(
&mut self,
- TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen: _ }: Self,
+ TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self,
+ replace: ReplaceOpt,
) {
- fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
+ fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
if let Some(new) = y {
if let Some(original) = x {
- original.merge(new);
+ original.merge(new, replace);
} else {
*x = Some(new);
}
}
}
- do_merge(&mut self.build, build);
- do_merge(&mut self.install, install);
- do_merge(&mut self.llvm, llvm);
- do_merge(&mut self.rust, rust);
- do_merge(&mut self.dist, dist);
+ self.changelog_seen.merge(changelog_seen, replace);
+ do_merge(&mut self.build, build, replace);
+ do_merge(&mut self.install, install, replace);
+ do_merge(&mut self.llvm, llvm, replace);
+ do_merge(&mut self.rust, rust, replace);
+ do_merge(&mut self.dist, dist, replace);
assert!(target.is_none(), "merging target-specific config is not currently supported");
}
}
@@ -547,10 +560,33 @@
}
impl Merge for $name {
- fn merge(&mut self, other: Self) {
+ fn merge(&mut self, other: Self, replace: ReplaceOpt) {
$(
- if !self.$field.is_some() {
- self.$field = other.$field;
+ match replace {
+ ReplaceOpt::IgnoreDuplicate => {
+ if self.$field.is_none() {
+ self.$field = other.$field;
+ }
+ },
+ ReplaceOpt::Override => {
+ if other.$field.is_some() {
+ self.$field = other.$field;
+ }
+ }
+ ReplaceOpt::ErrorOnDuplicate => {
+ if other.$field.is_some() {
+ if self.$field.is_some() {
+ if cfg!(test) {
+ panic!("overriding existing option")
+ } else {
+ eprintln!("overriding existing option: `{}`", stringify!($field));
+ crate::detail_exit(2);
+ }
+ } else {
+ self.$field = other.$field;
+ }
+ }
+ }
}
)*
}
@@ -623,6 +659,37 @@
}
}
+impl<T> Merge for Option<T> {
+ fn merge(&mut self, other: Self, replace: ReplaceOpt) {
+ match replace {
+ ReplaceOpt::IgnoreDuplicate => {
+ if self.is_none() {
+ *self = other;
+ }
+ }
+ ReplaceOpt::Override => {
+ if other.is_some() {
+ *self = other;
+ }
+ }
+ ReplaceOpt::ErrorOnDuplicate => {
+ if other.is_some() {
+ if self.is_some() {
+ if cfg!(test) {
+ panic!("overriding existing option")
+ } else {
+ eprintln!("overriding existing option");
+ crate::detail_exit(2);
+ }
+ } else {
+ *self = other;
+ }
+ }
+ }
+ }
+ }
+}
+
define_config! {
/// TOML representation of various global build decisions.
#[derive(Default)]
@@ -864,28 +931,27 @@
pub fn parse(args: &[String]) -> Config {
#[cfg(test)]
- let get_toml = |_: &_| TomlConfig::default();
+ fn get_toml(_: &Path) -> TomlConfig {
+ TomlConfig::default()
+ }
+
#[cfg(not(test))]
- let get_toml = |file: &Path| {
+ fn get_toml(file: &Path) -> TomlConfig {
let contents =
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
// TomlConfig and sub types to be monomorphized 5x by toml.
- match toml::from_str(&contents)
+ toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
- {
- Ok(table) => table,
- Err(err) => {
- eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+ .unwrap_or_else(|err| {
+ eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
crate::detail_exit(2);
- }
- }
- };
-
+ })
+ }
Self::parse_inner(args, get_toml)
}
- fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
+ fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
let mut flags = Flags::parse(&args);
let mut config = Config::default_opts();
@@ -998,9 +1064,41 @@
include_path.push("defaults");
include_path.push(format!("config.{}.toml", include));
let included_toml = get_toml(&include_path);
- toml.merge(included_toml);
+ toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
}
+ let mut override_toml = TomlConfig::default();
+ for option in flags.set.iter() {
+ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
+ toml::from_str(&option)
+ .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+ }
+
+ let mut err = match get_table(option) {
+ Ok(v) => {
+ override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+ continue;
+ }
+ Err(e) => e,
+ };
+ // We want to be able to set string values without quotes,
+ // like in `configure.py`. Try adding quotes around the right hand side
+ if let Some((key, value)) = option.split_once("=") {
+ if !value.contains('"') {
+ match get_table(&format!(r#"{key}="{value}""#)) {
+ Ok(v) => {
+ override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+ continue;
+ }
+ Err(e) => err = e,
+ }
+ }
+ }
+ eprintln!("failed to parse override `{option}`: `{err}");
+ crate::detail_exit(2)
+ }
+ toml.merge(override_toml, ReplaceOpt::Override);
+
config.changelog_seen = toml.changelog_seen;
let build = toml.build.unwrap_or_default();
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index d913ca2..4de84b5 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -1,13 +1,11 @@
-use super::{Config, Flags, TomlConfig};
+use super::{Config, Flags};
use clap::CommandFactory;
use std::{env, path::Path};
-fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
- |&_| toml::from_str(config).unwrap()
-}
-
fn parse(config: &str) -> Config {
- Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+ Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| {
+ toml::from_str(config).unwrap()
+ })
}
#[test]
@@ -94,3 +92,70 @@
fn clap_verify() {
Flags::command().debug_assert();
}
+
+#[test]
+fn override_toml() {
+ let config = Config::parse_inner(
+ &[
+ "check".to_owned(),
+ "--config=/does/not/exist".to_owned(),
+ "--set=changelog-seen=1".to_owned(),
+ "--set=rust.lto=fat".to_owned(),
+ "--set=rust.deny-warnings=false".to_owned(),
+ "--set=build.gdb=\"bar\"".to_owned(),
+ "--set=build.tools=[\"cargo\"]".to_owned(),
+ "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
+ ],
+ |&_| {
+ toml::from_str(
+ r#"
+changelog-seen = 0
+[rust]
+lto = "off"
+deny-warnings = true
+
+[build]
+gdb = "foo"
+tools = []
+
+[llvm]
+download-ci-llvm = false
+build-config = {}
+ "#,
+ )
+ .unwrap()
+ },
+ );
+ assert_eq!(config.changelog_seen, Some(1), "setting top-level value");
+ assert_eq!(
+ config.rust_lto,
+ crate::config::RustcLto::Fat,
+ "setting string value without quotes"
+ );
+ assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
+ assert_eq!(config.deny_warnings, false, "setting boolean value");
+ assert_eq!(
+ config.tools,
+ Some(["cargo".to_string()].into_iter().collect()),
+ "setting list value"
+ );
+ assert_eq!(
+ config.llvm_build_config,
+ [("foo".to_string(), "bar".to_string())].into_iter().collect(),
+ "setting dictionary value"
+ );
+}
+
+#[test]
+#[should_panic]
+fn override_toml_duplicate() {
+ Config::parse_inner(
+ &[
+ "check".to_owned(),
+ "--config=/does/not/exist".to_owned(),
+ "--set=changelog-seen=1".to_owned(),
+ "--set=changelog-seen=2".to_owned(),
+ ],
+ |&_| toml::from_str("changelog-seen = 0").unwrap(),
+ );
+}
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 9cead7a..b498453 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1071,7 +1071,11 @@
tarball.add_file(&cargo, "bin", 0o755);
tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
- tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
+ tarball.add_renamed_file(
+ etc.join("cargo.bashcomp.sh"),
+ "src/etc/bash_completion.d",
+ "cargo",
+ );
tarball.add_dir(etc.join("man"), "share/man/man1");
tarball.add_legal_and_readme_to("share/doc/cargo");
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 8f5d9bb..b52c3b6 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -839,6 +839,8 @@
)+
cargo.rustdocflag("--document-private-items");
+ // Since we always pass --document-private-items, there's no need to warn about linking to private items.
+ cargo.rustdocflag("-Arustdoc::private-intra-doc-links");
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("--generate-link-to-definition");
@@ -882,7 +884,8 @@
// "cargo-credential-wincred",
]
);
-tool_doc!(Tidy, "tidy", "src/tools/tidy", ["tidy"]);
+tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["tidy"]);
+tool_doc!(Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, ["bootstrap"]);
#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 25df5b2..c7969d2 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -123,7 +123,7 @@
/// This is only required on NixOS and uses the PatchELF utility to
/// change the interpreter/RPATH of ELF executables.
///
- /// Please see https://nixos.org/patchelf.html for more information
+ /// Please see <https://nixos.org/patchelf.html> for more information
fn fix_bin_or_dylib(&self, fname: &Path) {
assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
println!("attempting to patch {}", fname.display());
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index d8b298b..80e7157 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -158,6 +158,9 @@
#[arg(global(true))]
/// paths for the subcommand
pub paths: Vec<PathBuf>,
+ /// override options in config.toml
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")]
+ pub set: Vec<String>,
/// arguments passed to subcommands
#[arg(global(true), last(true), value_name = "ARGS")]
pub free_args: Vec<String>,
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 6ee50ee..943f513 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1011,6 +1011,8 @@
}
/// Return a `Group` guard for a [`Step`] that is built for each `--stage`.
+ ///
+ /// [`Step`]: crate::builder::Step
fn msg(
&self,
action: impl Into<Kind>,
@@ -1035,6 +1037,8 @@
}
/// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`.
+ ///
+ /// [`Step`]: crate::builder::Step
fn msg_unstaged(
&self,
action: impl Into<Kind>,
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index e19d56c..5990f33 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -14,6 +14,25 @@
use std::time::{Duration, Instant, SystemTime};
use sysinfo::{CpuExt, System, SystemExt};
+// Update this number whenever a breaking change is made to the build metrics.
+//
+// The output format is versioned for two reasons:
+//
+// - The metadata is intended to be consumed by external tooling, and exposing a format version
+// helps the tools determine whether they're compatible with a metrics file.
+//
+// - If a developer enables build metrics in their local checkout, making a breaking change to the
+// metrics format would result in a hard-to-diagnose error message when an existing metrics file
+// is not compatible with the new changes. With a format version number, bootstrap can discard
+// incompatible metrics files instead of appending metrics to them.
+//
+// Version changelog:
+//
+// - v0: initial version
+// - v1: replaced JsonNode::Test with JsonNode::TestSuite
+//
+const CURRENT_FORMAT_VERSION: usize = 1;
+
pub(crate) struct BuildMetrics {
state: RefCell<MetricsState>,
}
@@ -57,7 +76,7 @@
duration_excluding_children_sec: Duration::ZERO,
children: Vec::new(),
- tests: Vec::new(),
+ test_suites: Vec::new(),
});
}
@@ -84,6 +103,17 @@
}
}
+ pub(crate) fn begin_test_suite(&self, metadata: TestSuiteMetadata, builder: &Builder<'_>) {
+ // Do not record dry runs, as they'd be duplicates of the actual steps.
+ if builder.config.dry_run() {
+ return;
+ }
+
+ let mut state = self.state.borrow_mut();
+ let step = state.running_steps.last_mut().unwrap();
+ step.test_suites.push(TestSuite { metadata, tests: Vec::new() });
+ }
+
pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome, builder: &Builder<'_>) {
// Do not record dry runs, as they'd be duplicates of the actual steps.
if builder.config.dry_run() {
@@ -91,12 +121,13 @@
}
let mut state = self.state.borrow_mut();
- state
- .running_steps
- .last_mut()
- .unwrap()
- .tests
- .push(Test { name: name.to_string(), outcome });
+ let step = state.running_steps.last_mut().unwrap();
+
+ if let Some(test_suite) = step.test_suites.last_mut() {
+ test_suite.tests.push(Test { name: name.to_string(), outcome });
+ } else {
+ panic!("metrics.record_test() called without calling metrics.begin_test_suite() first");
+ }
}
fn collect_stats(&self, state: &mut MetricsState) {
@@ -131,7 +162,20 @@
// Some of our CI builds consist of multiple independent CI invocations. Ensure all the
// previous invocations are still present in the resulting file.
let mut invocations = match std::fs::read(&dest) {
- Ok(contents) => t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations,
+ Ok(contents) => {
+ // We first parse just the format_version field to have the check succeed even if
+ // the rest of the contents are not valid anymore.
+ let version: OnlyFormatVersion = t!(serde_json::from_slice(&contents));
+ if version.format_version == CURRENT_FORMAT_VERSION {
+ t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
+ } else {
+ println!(
+ "warning: overriding existing build/metrics.json, as it's not \
+ compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
+ );
+ Vec::new()
+ }
+ }
Err(err) => {
if err.kind() != std::io::ErrorKind::NotFound {
panic!("failed to open existing metrics file at {}: {err}", dest.display());
@@ -149,7 +193,7 @@
children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
});
- let json = JsonRoot { system_stats, invocations };
+ let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations };
t!(std::fs::create_dir_all(dest.parent().unwrap()));
let mut file = BufWriter::new(t!(File::create(&dest)));
@@ -159,11 +203,7 @@
fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
let mut children = Vec::new();
children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child)));
- children.extend(
- step.tests
- .into_iter()
- .map(|test| JsonNode::Test { name: test.name, outcome: test.outcome }),
- );
+ children.extend(step.test_suites.into_iter().map(JsonNode::TestSuite));
JsonNode::RustbuildStep {
type_: step.type_,
@@ -198,17 +238,14 @@
duration_excluding_children_sec: Duration,
children: Vec<StepMetrics>,
- tests: Vec<Test>,
-}
-
-struct Test {
- name: String,
- outcome: TestOutcome,
+ test_suites: Vec<TestSuite>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
struct JsonRoot {
+ #[serde(default)] // For version 0 the field was not present.
+ format_version: usize,
system_stats: JsonInvocationSystemStats,
invocations: Vec<JsonInvocation>,
}
@@ -237,11 +274,39 @@
children: Vec<JsonNode>,
},
- Test {
- name: String,
- #[serde(flatten)]
- outcome: TestOutcome,
+ TestSuite(TestSuite),
+}
+
+#[derive(Serialize, Deserialize)]
+struct TestSuite {
+ metadata: TestSuiteMetadata,
+ tests: Vec<Test>,
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(tag = "kind", rename_all = "snake_case")]
+pub(crate) enum TestSuiteMetadata {
+ CargoPackage {
+ crates: Vec<String>,
+ target: String,
+ host: String,
+ stage: u32,
},
+ Compiletest {
+ suite: String,
+ mode: String,
+ compare_mode: Option<String>,
+ target: String,
+ host: String,
+ stage: u32,
+ },
+}
+
+#[derive(Serialize, Deserialize)]
+pub(crate) struct Test {
+ name: String,
+ #[serde(flatten)]
+ outcome: TestOutcome,
}
#[derive(Serialize, Deserialize)]
@@ -266,3 +331,9 @@
struct JsonStepSystemStats {
cpu_utilization_percent: f64,
}
+
+#[derive(Deserialize)]
+struct OnlyFormatVersion {
+ #[serde(default)] // For version 0 the field was not present.
+ format_version: usize,
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 2b72d6c..44cd84b 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -317,6 +317,17 @@
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
cargo.env("PATH", &path_for_cargo(builder, compiler));
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: vec!["cargo".into()],
+ target: self.host.triple.to_string(),
+ host: self.host.triple.to_string(),
+ stage: self.stage,
+ },
+ builder,
+ );
+
let _time = util::timeit(&builder);
add_flags_and_try_run_tests(builder, &mut cargo);
}
@@ -944,28 +955,6 @@
.or_else(|| get_browser_ui_test_version_inner(npm, true))
}
-fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
- match fs::read_to_string(
- src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
- ) {
- Ok(v) => {
- if v.trim() != installed_version {
- eprintln!(
- "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
- one used in the CI (`{}`)",
- installed_version, v
- );
- eprintln!(
- "You can install this version using `npm update browser-ui-test` or by using \
- `npm install browser-ui-test@{}`",
- v,
- );
- }
- }
- Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
- }
-}
-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocGUI {
pub target: TargetSelection,
@@ -997,79 +986,30 @@
}
fn run(self, builder: &Builder<'_>) {
- let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available");
- let npm = builder.config.npm.as_ref().expect("npm isn't available");
-
builder.ensure(compile::Std::new(self.compiler, self.target));
- // The goal here is to check if the necessary packages are installed, and if not, we
- // panic.
- match get_browser_ui_test_version(&npm) {
- Some(version) => {
- // We also check the version currently used in CI and emit a warning if it's not the
- // same one.
- compare_browser_ui_test_version(&version, &builder.build.src);
- }
- None => {
- eprintln!(
- "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
- dependency is missing",
- );
- eprintln!(
- "If you want to install the `{0}` dependency, run `npm install {0}`",
- "browser-ui-test",
- );
- panic!("Cannot run rustdoc-gui tests");
- }
- }
+ let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
let out_dir = builder.test_out(self.target).join("rustdoc-gui");
-
- // We remove existing folder to be sure there won't be artifacts remaining.
builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler));
- let src_path = builder.build.src.join("tests/rustdoc-gui/src");
- // We generate docs for the libraries present in the rustdoc-gui's src folder.
- for entry in src_path.read_dir().expect("read_dir call failed") {
- if let Ok(entry) = entry {
- let path = entry.path();
-
- if !path.is_dir() {
- continue;
- }
-
- let mut cargo = Command::new(&builder.initial_cargo);
- cargo
- .arg("doc")
- .arg("--target-dir")
- .arg(&out_dir)
- .env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(self.compiler))
- .env("RUSTC", builder.rustc(self.compiler))
- .current_dir(path);
- // FIXME: implement a `// compile-flags` command or similar
- // instead of hard-coding this test
- if entry.file_name() == "link_to_definition" {
- cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
- } else if entry.file_name() == "scrape_examples" {
- cargo.arg("-Zrustdoc-scrape-examples");
- } else if entry.file_name() == "extend_css" {
- cargo.env("RUSTDOCFLAGS", &format!("--extend-css extra.css"));
- }
- builder.run(&mut cargo);
- }
+ if let Some(src) = builder.config.src.to_str() {
+ cmd.arg("--rust-src").arg(src);
}
- // We now run GUI tests.
- let mut command = Command::new(&nodejs);
- command
- .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
- .arg("--jobs")
- .arg(&builder.jobs().to_string())
- .arg("--doc-folder")
- .arg(out_dir.join("doc"))
- .arg("--tests-folder")
- .arg(builder.build.src.join("tests/rustdoc-gui"));
+ if let Some(out_dir) = out_dir.to_str() {
+ cmd.arg("--out-dir").arg(out_dir);
+ }
+
+ if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
+ cmd.arg("--initial-cargo").arg(initial_cargo);
+ }
+
+ cmd.arg("--jobs").arg(builder.jobs().to_string());
+
+ cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
+ .env("RUSTC", builder.rustc(self.compiler));
+
for path in &builder.paths {
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
if !p.ends_with(".goml") {
@@ -1077,14 +1017,25 @@
panic!("Cannot run rustdoc-gui tests");
}
if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
- command.arg("--file").arg(name);
+ cmd.arg("--goml-file").arg(name);
}
}
}
+
for test_arg in builder.config.test_args() {
- command.arg(test_arg);
+ cmd.arg("--test-arg").arg(test_arg);
}
- builder.run(&mut command);
+
+ if let Some(ref nodejs) = builder.config.nodejs {
+ cmd.arg("--nodejs").arg(nodejs);
+ }
+
+ if let Some(ref npm) = builder.config.npm {
+ cmd.arg("--npm").arg(npm);
+ }
+
+ let _time = util::timeit(&builder);
+ crate::render_tests::try_run_tests(builder, &mut cmd);
}
}
@@ -1759,6 +1710,19 @@
builder.ci_env.force_coloring_in_ci(&mut cmd);
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: None,
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target
@@ -1768,6 +1732,20 @@
if let Some(compare_mode) = compare_mode {
cmd.arg("--compare-mode").arg(compare_mode);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: Some(compare_mode.into()),
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target
@@ -2094,6 +2072,17 @@
let mut cargo =
prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
let _time = util::timeit(&builder);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: crates.iter().map(|c| c.to_string()).collect(),
+ target: target.triple.to_string(),
+ host: compiler.host.triple.to_string(),
+ stage: compiler.stage,
+ },
+ builder,
+ );
add_flags_and_try_run_tests(builder, &mut cargo)
}
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index f13d365..b3791ef 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -302,6 +302,7 @@
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
SuggestTests, "src/tools/suggest-tests", "suggest-tests";
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
+ RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 2e1adbf..9bfdc77 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -488,7 +488,7 @@
}
}
-/// Adapted from https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079
+/// Adapted from <https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079>
///
/// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
/// directory to the linker flags, otherwise there will be linker errors about the profiler runtime
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
index 3ac5343..420c42b 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
@@ -33,6 +33,11 @@
ENV HOSTS=arm-unknown-linux-gnueabi,aarch64-unknown-linux-musl
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs --musl-root-aarch64=/usr/local/aarch64-linux-musl \
- --set target.aarch64-unknown-linux-musl.crt-static=false
+ENV RUST_CONFIGURE_ARGS \
+ --enable-full-tools \
+ --disable-docs \
+ --musl-root-aarch64=/usr/local/aarch64-linux-musl \
+ --enable-sanitizers \
+ --enable-profiler \
+ --set target.aarch64-unknown-linux-musl.crt-static=false
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md
index 38fd1db..1fa9f81 100644
--- a/src/doc/rustdoc/src/how-to-write-documentation.md
+++ b/src/doc/rustdoc/src/how-to-write-documentation.md
@@ -165,15 +165,15 @@
### Strikethrough
Text may be rendered with a horizontal line through the center by wrapping the
-text with two tilde characters on each side:
+text with one or two tilde characters on each side:
```text
-An example of ~~strikethrough text~~.
+An example of ~~strikethrough text~~. You can also use ~single tildes~.
```
This example will render as:
-> An example of ~~strikethrough text~~.
+> An example of ~~strikethrough text~~. You can also use ~single tildes~.
This follows the [GitHub Strikethrough extension][strikethrough].
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 4eddd5c..9f65f1e 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -19,6 +19,7 @@
complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -62,6 +63,7 @@
complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -91,6 +93,7 @@
complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets'
complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
@@ -125,6 +128,7 @@
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix
complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
@@ -155,6 +159,7 @@
complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -184,6 +189,7 @@
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
@@ -214,6 +220,7 @@
complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser'
complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format'
complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
@@ -251,6 +258,7 @@
complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure'
complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests'
complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests'
@@ -288,6 +296,7 @@
complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -317,6 +326,7 @@
complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
@@ -347,6 +357,7 @@
complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -376,6 +387,7 @@
complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -406,6 +418,7 @@
complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -435,6 +448,7 @@
complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -464,6 +478,7 @@
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 59fabf5..569c186 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -43,6 +43,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -93,6 +94,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -129,6 +131,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -170,6 +173,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -207,6 +211,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -243,6 +248,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -280,6 +286,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'open the docs in a browser')
[CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -324,6 +331,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure')
[CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests')
[CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests')
@@ -368,6 +376,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -404,6 +413,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -441,6 +451,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -477,6 +488,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -514,6 +526,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -550,6 +563,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -586,6 +600,7 @@
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index 931cc43..322afdb 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -61,7 +61,7 @@
case "${cmd}" in
x.py)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -155,6 +155,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -163,7 +167,7 @@
return 0
;;
x.py__bench)
- opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -261,6 +265,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -269,7 +277,7 @@
return 0
;;
x.py__build)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -363,6 +371,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -371,7 +383,7 @@
return 0
;;
x.py__check)
- opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -465,6 +477,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -473,7 +489,7 @@
return 0
;;
x.py__clean)
- opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -567,6 +583,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -575,7 +595,7 @@
return 0
;;
x.py__clippy)
- opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -685,6 +705,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -693,7 +717,7 @@
return 0
;;
x.py__dist)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -787,6 +811,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -795,7 +823,7 @@
return 0
;;
x.py__doc)
- opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -889,6 +917,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -897,7 +929,7 @@
return 0
;;
x.py__fix)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -991,6 +1023,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -999,7 +1035,7 @@
return 0
;;
x.py__fmt)
- opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1093,6 +1129,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -1101,7 +1141,7 @@
return 0
;;
x.py__install)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1195,6 +1235,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -1203,7 +1247,7 @@
return 0
;;
x.py__run)
- opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1301,6 +1345,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -1309,7 +1357,7 @@
return 0
;;
x.py__setup)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1403,6 +1451,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -1411,7 +1463,7 @@
return 0
;;
x.py__suggest)
- opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1505,6 +1557,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
@@ -1513,7 +1569,7 @@
return 0
;;
x.py__test)
- opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1631,6 +1687,10 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
*)
COMPREPLY=()
;;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 38664c3..e9ccea2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -401,12 +401,18 @@
.unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
}
- /// Finds the `doc` attribute as a NameValue and returns the corresponding
- /// value found.
- pub(crate) fn doc_value(&self) -> Option<String> {
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ pub(crate) fn doc_value(&self) -> String {
self.attrs.doc_value()
}
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+ /// documentation but it is empty (e.g. `#[doc = ""]`).
+ pub(crate) fn opt_doc_value(&self) -> Option<String> {
+ self.attrs.opt_doc_value()
+ }
+
pub(crate) fn from_def_id_and_parts(
def_id: DefId,
name: Option<Symbol>,
@@ -443,12 +449,6 @@
}
}
- /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
- /// with newlines.
- pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
- self.attrs.collapsed_doc_value()
- }
-
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
use crate::html::format::{href, link_tooltip};
@@ -1068,17 +1068,6 @@
}
}
-/// Collapse a collection of [`DocFragment`]s into one string,
-/// handling indentation and newlines as needed.
-pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
- let mut acc = String::new();
- for frag in doc_strings {
- add_doc_fragment(&mut acc, frag);
- }
- acc.pop();
- acc
-}
-
/// A link that has not yet been rendered.
///
/// This link will be turned into a rendered link by [`Item::links`].
@@ -1163,29 +1152,23 @@
Attributes { doc_strings, other_attrs }
}
- /// Finds the `doc` attribute as a NameValue and returns the corresponding
- /// value found.
- pub(crate) fn doc_value(&self) -> Option<String> {
- let mut iter = self.doc_strings.iter();
-
- let ori = iter.next()?;
- let mut out = String::new();
- add_doc_fragment(&mut out, ori);
- for new_frag in iter {
- add_doc_fragment(&mut out, new_frag);
- }
- out.pop();
- if out.is_empty() { None } else { Some(out) }
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ pub(crate) fn doc_value(&self) -> String {
+ self.opt_doc_value().unwrap_or_default()
}
- /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
- /// with newlines.
- pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
- if self.doc_strings.is_empty() {
- None
- } else {
- Some(collapse_doc_fragments(&self.doc_strings))
- }
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+ /// documentation but it is empty (e.g. `#[doc = ""]`).
+ pub(crate) fn opt_doc_value(&self) -> Option<String> {
+ (!self.doc_strings.is_empty()).then(|| {
+ let mut res = String::new();
+ for frag in &self.doc_strings {
+ add_doc_fragment(&mut res, frag);
+ }
+ res.pop();
+ res
+ })
}
pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index d8c91a9..3949542 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,7 +1,5 @@
use super::*;
-use crate::clean::collapse_doc_fragments;
-
use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::DUMMY_SP;
@@ -22,7 +20,8 @@
create_default_session_globals_then(|| {
let mut s = create_doc_fragment(input);
unindent_doc_fragments(&mut s);
- assert_eq!(collapse_doc_fragments(&s), expected);
+ let attrs = Attributes { doc_strings: s, other_attrs: Default::default() };
+ assert_eq!(attrs.doc_value(), expected);
});
}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a6be132..e10a629 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -367,7 +367,7 @@
let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
- if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
+ if krate.module.doc_value().is_empty() {
let help = format!(
"The following guide may be of use:\n\
{}/rustdoc/how-to-write-documentation.html",
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 575d8ee..f6631b6 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1237,7 +1237,7 @@
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
// anything else, this will combine them for us.
let attrs = Attributes::from_ast(ast_attrs);
- if let Some(doc) = attrs.collapsed_doc_value() {
+ if let Some(doc) = attrs.opt_doc_value() {
// Use the outermost invocation, so that doctest names come from where the docs were written.
let span = ast_attrs
.iter()
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c0730e9..c4758fd 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -327,9 +327,8 @@
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
- let desc = item.doc_value().map_or_else(String::new, |x| {
- short_markdown_summary(x.as_str(), &item.link_names(self.cache))
- });
+ let desc =
+ short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
let ty = item.type_();
if ty != ItemType::StructField
|| u16::from_str_radix(s.as_str(), 10).is_err()
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 01a92f6..56af257 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -184,11 +184,8 @@
};
title.push_str(" - Rust");
let tyname = it.type_();
- let desc = it
- .doc_value()
- .as_ref()
- .map(|doc| plain_text_summary(doc, &it.link_names(&self.cache())));
- let desc = if let Some(desc) = desc {
+ let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache()));
+ let desc = if !desc.is_empty() {
desc
} else if it.is_crate() {
format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 0a2f5f6..42e27d3 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -468,7 +468,8 @@
if !show_def_docs {
return Ok(());
}
- if let Some(s) = item.doc_value() {
+ let s = item.doc_value();
+ if !s.is_empty() {
let (mut summary_html, has_more_content) =
MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
@@ -511,7 +512,7 @@
heading_offset: HeadingOffset,
) -> impl fmt::Display + 'a + Captures<'cx> {
display_fn(move |f| {
- if let Some(s) = item.collapsed_doc_value() {
+ if let Some(s) = item.opt_doc_value() {
debug!("Doc block: =====\n{}\n=====", s);
if is_collapsible {
write!(
@@ -1476,7 +1477,7 @@
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
// We need the stability of the item from the trait
// because impls can't have a stability.
- if item.doc_value().is_some() {
+ if !item.doc_value().is_empty() {
document_item_info(cx, it, Some(parent))
.render_into(&mut info_buffer)
.unwrap();
@@ -1747,7 +1748,7 @@
write!(w, "</summary>")
}
- if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
+ if let Some(ref dox) = i.impl_item.opt_doc_value() {
if trait_.is_none() && i.inner_impl().items.is_empty() {
w.write_str(
"<div class=\"item-info\">\
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 4cc81e8..2961a28 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -420,9 +420,9 @@
_ => "",
};
- let doc_value = myitem.doc_value().unwrap_or_default();
w.write_str(ITEM_TABLE_ROW_OPEN);
- let docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string();
+ let docs =
+ MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
let (docs_before, docs_after) = if docs.is_empty() {
("", "")
} else {
@@ -1338,7 +1338,7 @@
clean::VariantKind::Tuple(fields) => {
// Documentation on tuple variant fields is rare, so to reduce noise we only emit
// the section if at least one field is documented.
- if fields.iter().any(|f| f.doc_value().is_some()) {
+ if fields.iter().any(|f| !f.doc_value().is_empty()) {
Some(("Tuple Fields", fields))
} else {
None
@@ -1541,11 +1541,12 @@
write!(w, "{}", document_type_layout(cx, def_id));
}
-fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it, cx.tcx());
+fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
+ let mut buffer = Buffer::new();
+ wrap_item(&mut buffer, |buffer| {
+ render_attributes_in_code(buffer, it, cx.tcx());
write!(
- w,
+ buffer,
"{vis}static {mutability}{name}: {typ}",
vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
mutability = s.mutability.print_with_space(),
@@ -1553,7 +1554,10 @@
typ = s.type_.print(cx)
);
});
- write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+
+ write!(w, "{}", buffer.into_inner()).unwrap();
+
+ write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
}
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index a3be6dd..846299f 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -28,9 +28,7 @@
// has since been learned.
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
if let Some((fqp, _)) = cache.paths.get(&parent) {
- let desc = item
- .doc_value()
- .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
+ let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
cache.search_index.push(IndexItem {
ty: item.type_(),
name: item.name.unwrap(),
@@ -45,10 +43,8 @@
}
}
- let crate_doc = krate
- .module
- .doc_value()
- .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache)));
+ let crate_doc =
+ short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
// we need the alias element to have an array of items.
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b1cef20..935bb72 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -40,7 +40,7 @@
(String::from(&**link), id_from_item_default(id.into(), self.tcx))
})
.collect();
- let docs = item.attrs.collapsed_doc_value();
+ let docs = item.opt_doc_value();
let attrs = item.attributes(self.tcx, true);
let span = item.span(self.tcx);
let visibility = item.visibility(self.tcx);
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index be5286b..6ead0cd 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -206,13 +206,7 @@
let has_docs = !i.attrs.doc_strings.is_empty();
let mut tests = Tests { found_tests: 0 };
- find_testable_code(
- &i.attrs.collapsed_doc_value().unwrap_or_default(),
- &mut tests,
- ErrorCodes::No,
- false,
- None,
- );
+ find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
let has_doc_example = tests.found_tests != 0;
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 10295cb..b6cd897 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -34,9 +34,7 @@
impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
-
- look_for_tests(self.cx, &dox, item);
+ look_for_tests(self.cx, &item.doc_value(), item);
self.visit_item_recur(item)
}
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index 423230c..a10d5fd 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -18,7 +18,7 @@
// If non-local, no need to check anything.
return;
};
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+ let dox = item.doc_value();
if !dox.is_empty() {
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 8f873db..f489f50 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -17,7 +17,7 @@
use crate::passes::source_span_for_markdown_range;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
- if let Some(dox) = &item.attrs.collapsed_doc_value() {
+ if let Some(dox) = &item.opt_doc_value() {
let sp = item.attr_span(cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
for code_block in markdown::rust_code_blocks(dox, &extra) {
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 4f72df5..f040364 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -15,7 +15,7 @@
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
// If non-local, no need to check anything.
else { return };
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+ let dox = item.doc_value();
if !dox.is_empty() {
let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
index 33cef82..683c224 100644
--- a/src/librustdoc/passes/lint/unescaped_backticks.rs
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -16,7 +16,7 @@
return;
};
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+ let dox = item.doc_value();
if dox.is_empty() {
return;
}
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index cba55e5..73fc26a 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -194,7 +194,7 @@
})
{
return None;
- } else if imp.items.is_empty() && i.doc_value().is_none() {
+ } else if imp.items.is_empty() && i.doc_value().is_empty() {
return None;
}
}
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index e5297d4..d2f2583 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -3,6 +3,9 @@
version = "0.0.0"
edition = "2021"
+[lib]
+doctest = false
+
[dependencies]
colored = "2"
diff = "0.1.10"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index ba68b5e..f796c89 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -69,6 +69,12 @@
}
}
+impl Default for Mode {
+ fn default() -> Self {
+ Mode::Ui
+ }
+}
+
impl Mode {
pub fn disambiguator(self) -> &'static str {
// Pretty-printing tests could run concurrently, and if they do,
@@ -125,7 +131,7 @@
}
/// Configuration for compiletest
-#[derive(Debug, Clone)]
+#[derive(Debug, Default, Clone)]
pub struct Config {
/// `true` to overwrite stderr/stdout files instead of complaining about changes in output.
pub bless: bool,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
new file mode 100644
index 0000000..fc48d01
--- /dev/null
+++ b/src/tools/compiletest/src/lib.rs
@@ -0,0 +1,1136 @@
+#![crate_name = "compiletest"]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
+
+extern crate test;
+
+#[cfg(test)]
+mod tests;
+
+pub mod common;
+pub mod compute_diff;
+pub mod errors;
+pub mod header;
+mod json;
+mod raise_fd_limit;
+mod read2;
+pub mod runtest;
+pub mod util;
+
+use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
+use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
+use crate::util::logv;
+use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use core::panic;
+use getopts::Options;
+use lazycell::AtomicLazyCell;
+use std::collections::BTreeSet;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, ErrorKind};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::time::SystemTime;
+use std::{env, vec};
+use test::ColorConfig;
+use tracing::*;
+use walkdir::WalkDir;
+
+use self::header::{make_test_description, EarlyProps};
+use crate::header::HeadersCache;
+use std::sync::Arc;
+
+pub fn parse_config(args: Vec<String>) -> Config {
+ let mut opts = Options::new();
+ opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
+ .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
+ .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
+ .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
+ .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
+ .reqopt("", "python", "path to python to use for doc tests", "PATH")
+ .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
+ .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
+ .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
+ .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
+ .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
+ .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
+ .reqopt("", "src-base", "directory to scan for test files", "PATH")
+ .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
+ .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
+ .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
+ .reqopt(
+ "",
+ "mode",
+ "which sort of compile tests to run",
+ "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
+ | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
+ )
+ .reqopt(
+ "",
+ "suite",
+ "which suite of compile tests to run. used for nicer error reporting.",
+ "SUITE",
+ )
+ .optopt(
+ "",
+ "pass",
+ "force {check,build,run}-pass tests to this mode.",
+ "check | build | run",
+ )
+ .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
+ .optflag("", "ignored", "run tests marked as ignored")
+ .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
+ .optflag("", "exact", "filters match exactly")
+ .optopt(
+ "",
+ "runtool",
+ "supervisor program to run tests under \
+ (eg. emulator, valgrind)",
+ "PROGRAM",
+ )
+ .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
+ .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
+ .optflag("", "optimize-tests", "run tests with optimizations enabled")
+ .optflag("", "verbose", "run tests verbosely, showing all output")
+ .optflag(
+ "",
+ "bless",
+ "overwrite stderr/stdout files instead of complaining about a mismatch",
+ )
+ .optflag("", "quiet", "print one character per test instead of one line")
+ .optopt("", "color", "coloring: auto, always, never", "WHEN")
+ .optflag("", "json", "emit json output instead of plaintext output")
+ .optopt("", "logfile", "file to log test execution to", "FILE")
+ .optopt("", "target", "the target to build for", "TARGET")
+ .optopt("", "host", "the host to build for", "HOST")
+ .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
+ .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
+ .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
+ .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
+ .optflag("", "system-llvm", "is LLVM the system LLVM")
+ .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
+ .optopt("", "adb-path", "path to the android debugger", "PATH")
+ .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
+ .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
+ .reqopt("", "cc", "path to a C compiler", "PATH")
+ .reqopt("", "cxx", "path to a C++ compiler", "PATH")
+ .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
+ .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
+ .optopt("", "ar", "path to an archiver", "PATH")
+ .optopt("", "target-linker", "path to a linker for the target", "PATH")
+ .optopt("", "host-linker", "path to a linker for the host", "PATH")
+ .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
+ .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
+ .optopt("", "nodejs", "the name of nodejs", "PATH")
+ .optopt("", "npm", "the name of npm", "PATH")
+ .optopt("", "remote-test-client", "path to the remote test client", "PATH")
+ .optopt(
+ "",
+ "compare-mode",
+ "mode describing what file the actual ui output will be compared to",
+ "COMPARE MODE",
+ )
+ .optflag(
+ "",
+ "rustfix-coverage",
+ "enable this to generate a Rustfix coverage file, which is saved in \
+ `./<build_base>/rustfix_missing_coverage.txt`",
+ )
+ .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
+ .optflag("", "only-modified", "only run tests that result been modified")
+ .optflag("", "nocapture", "")
+ .optflag("h", "help", "show this message")
+ .reqopt("", "channel", "current Rust channel", "CHANNEL")
+ .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
+ .optopt("", "edition", "default Rust edition", "EDITION");
+
+ let (argv0, args_) = args.split_first().unwrap();
+ if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ println!();
+ panic!()
+ }
+
+ let matches = &match opts.parse(args_) {
+ Ok(m) => m,
+ Err(f) => panic!("{:?}", f),
+ };
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ println!();
+ panic!()
+ }
+
+ fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
+ match m.opt_str(nm) {
+ Some(s) => PathBuf::from(&s),
+ None => panic!("no option (=path) found for {}", nm),
+ }
+ }
+
+ fn make_absolute(path: PathBuf) -> PathBuf {
+ if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
+ }
+
+ let target = opt_str2(matches.opt_str("target"));
+ let android_cross_path = opt_path(matches, "android-cross-path");
+ let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
+ let (gdb, gdb_version, gdb_native_rust) =
+ analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
+ let (lldb_version, lldb_native_rust) = matches
+ .opt_str("lldb-version")
+ .as_deref()
+ .and_then(extract_lldb_version)
+ .map(|(v, b)| (Some(v), b))
+ .unwrap_or((None, false));
+ let color = match matches.opt_str("color").as_deref() {
+ Some("auto") | None => ColorConfig::AutoColor,
+ Some("always") => ColorConfig::AlwaysColor,
+ Some("never") => ColorConfig::NeverColor,
+ Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
+ };
+ let llvm_version =
+ matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+ || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
+ );
+
+ let src_base = opt_path(matches, "src-base");
+ let run_ignored = matches.opt_present("ignored");
+ let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
+ let has_tidy = if mode == Mode::Rustdoc {
+ Command::new("tidy")
+ .arg("--version")
+ .stdout(Stdio::null())
+ .status()
+ .map_or(false, |status| status.success())
+ } else {
+ // Avoid spawning an external command when we know tidy won't be used.
+ false
+ };
+ Config {
+ bless: matches.opt_present("bless"),
+ compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
+ run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
+ rustc_path: opt_path(matches, "rustc-path"),
+ rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
+ rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
+ python: matches.opt_str("python").unwrap(),
+ jsondocck_path: matches.opt_str("jsondocck-path"),
+ jsondoclint_path: matches.opt_str("jsondoclint-path"),
+ valgrind_path: matches.opt_str("valgrind-path"),
+ force_valgrind: matches.opt_present("force-valgrind"),
+ run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
+ llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
+ llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
+ src_base,
+ build_base: opt_path(matches, "build-base"),
+ sysroot_base: opt_path(matches, "sysroot-base"),
+ stage_id: matches.opt_str("stage-id").unwrap(),
+ mode,
+ suite: matches.opt_str("suite").unwrap(),
+ debugger: None,
+ run_ignored,
+ filters: matches.free.clone(),
+ skip: matches.opt_strs("skip"),
+ filter_exact: matches.opt_present("exact"),
+ force_pass_mode: matches.opt_str("pass").map(|mode| {
+ mode.parse::<PassMode>()
+ .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
+ }),
+ run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
+ "auto" => None,
+ "always" => Some(true),
+ "never" => Some(false),
+ _ => panic!("unknown `--run` option `{}` given", mode),
+ }),
+ logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
+ runtool: matches.opt_str("runtool"),
+ host_rustcflags: matches.opt_strs("host-rustcflags"),
+ target_rustcflags: matches.opt_strs("target-rustcflags"),
+ optimize_tests: matches.opt_present("optimize-tests"),
+ target,
+ host: opt_str2(matches.opt_str("host")),
+ cdb,
+ cdb_version,
+ gdb,
+ gdb_version,
+ gdb_native_rust,
+ lldb_version,
+ lldb_native_rust,
+ llvm_version,
+ system_llvm: matches.opt_present("system-llvm"),
+ android_cross_path,
+ adb_path: opt_str2(matches.opt_str("adb-path")),
+ adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
+ adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
+ && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
+ && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
+ lldb_python_dir: matches.opt_str("lldb-python-dir"),
+ verbose: matches.opt_present("verbose"),
+ format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
+ (true, true) => panic!("--quiet and --json are incompatible"),
+ (true, false) => test::OutputFormat::Terse,
+ (false, true) => test::OutputFormat::Json,
+ (false, false) => test::OutputFormat::Pretty,
+ },
+ only_modified: matches.opt_present("only-modified"),
+ color,
+ remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+ compare_mode: matches
+ .opt_str("compare-mode")
+ .map(|s| s.parse().expect("invalid --compare-mode provided")),
+ rustfix_coverage: matches.opt_present("rustfix-coverage"),
+ has_tidy,
+ channel: matches.opt_str("channel").unwrap(),
+ git_hash: matches.opt_present("git-hash"),
+ edition: matches.opt_str("edition"),
+
+ cc: matches.opt_str("cc").unwrap(),
+ cxx: matches.opt_str("cxx").unwrap(),
+ cflags: matches.opt_str("cflags").unwrap(),
+ cxxflags: matches.opt_str("cxxflags").unwrap(),
+ ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
+ target_linker: matches.opt_str("target-linker"),
+ host_linker: matches.opt_str("host-linker"),
+ llvm_components: matches.opt_str("llvm-components").unwrap(),
+ nodejs: matches.opt_str("nodejs"),
+ npm: matches.opt_str("npm"),
+
+ force_rerun: matches.opt_present("force-rerun"),
+
+ target_cfgs: AtomicLazyCell::new(),
+
+ nocapture: matches.opt_present("nocapture"),
+ }
+}
+
+pub fn log_config(config: &Config) {
+ let c = config;
+ logv(c, "configuration:".to_string());
+ logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
+ logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
+ logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
+ logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
+ logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
+ logv(c, format!("src_base: {:?}", config.src_base.display()));
+ logv(c, format!("build_base: {:?}", config.build_base.display()));
+ logv(c, format!("stage_id: {}", config.stage_id));
+ logv(c, format!("mode: {}", config.mode));
+ logv(c, format!("run_ignored: {}", config.run_ignored));
+ logv(c, format!("filters: {:?}", config.filters));
+ logv(c, format!("skip: {:?}", config.skip));
+ logv(c, format!("filter_exact: {}", config.filter_exact));
+ logv(
+ c,
+ format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
+ );
+ logv(c, format!("runtool: {}", opt_str(&config.runtool)));
+ logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
+ logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
+ logv(c, format!("target: {}", config.target));
+ logv(c, format!("host: {}", config.host));
+ logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
+ logv(c, format!("adb_path: {:?}", config.adb_path));
+ logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
+ logv(c, format!("adb_device_status: {}", config.adb_device_status));
+ logv(c, format!("ar: {}", config.ar));
+ logv(c, format!("target-linker: {:?}", config.target_linker));
+ logv(c, format!("host-linker: {:?}", config.host_linker));
+ logv(c, format!("verbose: {}", config.verbose));
+ logv(c, format!("format: {:?}", config.format));
+ logv(c, "\n".to_string());
+}
+
+pub fn opt_str(maybestr: &Option<String>) -> &str {
+ match *maybestr {
+ None => "(none)",
+ Some(ref s) => s,
+ }
+}
+
+pub fn opt_str2(maybestr: Option<String>) -> String {
+ match maybestr {
+ None => "(none)".to_owned(),
+ Some(s) => s,
+ }
+}
+
+pub fn run_tests(config: Arc<Config>) {
+ // If we want to collect rustfix coverage information,
+ // we first make sure that the coverage file does not exist.
+ // It will be created later on.
+ if config.rustfix_coverage {
+ let mut coverage_file_path = config.build_base.clone();
+ coverage_file_path.push("rustfix_missing_coverage.txt");
+ if coverage_file_path.exists() {
+ if let Err(e) = fs::remove_file(&coverage_file_path) {
+ panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
+ }
+ }
+ }
+
+ // sadly osx needs some file descriptor limits raised for running tests in
+ // parallel (especially when we have lots and lots of child processes).
+ // For context, see #8904
+ unsafe {
+ raise_fd_limit::raise_fd_limit();
+ }
+ // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
+ // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
+ env::set_var("__COMPAT_LAYER", "RunAsInvoker");
+
+ // Let tests know which target they're running as
+ env::set_var("TARGET", &config.target);
+
+ let opts = test_opts(&config);
+
+ let mut configs = Vec::new();
+ if let Mode::DebugInfo = config.mode {
+ // Debugging emscripten code doesn't make sense today
+ if !config.target.contains("emscripten") {
+ configs.extend(configure_cdb(&config));
+ configs.extend(configure_gdb(&config));
+ configs.extend(configure_lldb(&config));
+ }
+ } else {
+ configs.push(config.clone());
+ };
+
+ let mut tests = Vec::new();
+ for c in configs {
+ let mut found_paths = BTreeSet::new();
+ make_tests(c, &mut tests, &mut found_paths);
+ check_overlapping_tests(&found_paths);
+ }
+
+ tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+
+ let res = test::run_tests_console(&opts, tests);
+ match res {
+ Ok(true) => {}
+ Ok(false) => {
+ // We want to report that the tests failed, but we also want to give
+ // some indication of just what tests we were running. Especially on
+ // CI, where there can be cross-compiled tests for a lot of
+ // architectures, without this critical information it can be quite
+ // easy to miss which tests failed, and as such fail to reproduce
+ // the failure locally.
+
+ println!(
+ "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
+ config.suite,
+ config
+ .compare_mode
+ .as_ref()
+ .map(|c| format!(" compare_mode={:?}", c))
+ .unwrap_or_default(),
+ config.mode,
+ config.host,
+ config.target
+ );
+
+ std::process::exit(1);
+ }
+ Err(e) => {
+ // We don't know if tests passed or not, but if there was an error
+ // during testing we don't want to just succeed (we may not have
+ // tested something), so fail.
+ //
+ // This should realistically "never" happen, so don't try to make
+ // this a pretty error message.
+ panic!("I/O failure during tests: {:?}", e);
+ }
+ }
+}
+
+fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
+ config.cdb.as_ref()?;
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
+}
+
+fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
+ config.gdb_version?;
+
+ if config.matches_env("msvc") {
+ return None;
+ }
+
+ if config.remote_test_client.is_some() && !config.target.contains("android") {
+ println!(
+ "WARNING: debuginfo tests are not available when \
+ testing with remote"
+ );
+ return None;
+ }
+
+ if config.target.contains("android") {
+ println!(
+ "{} debug-info test uses tcp 5039 port.\
+ please reserve it",
+ config.target
+ );
+
+ // android debug-info test uses remote debugger so, we test 1 thread
+ // at once as they're all sharing the same TCP port to communicate
+ // over.
+ //
+ // we should figure out how to lift this restriction! (run them all
+ // on different ports allocated dynamically).
+ env::set_var("RUST_TEST_THREADS", "1");
+ }
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
+}
+
+fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
+ config.lldb_python_dir.as_ref()?;
+
+ if let Some(350) = config.lldb_version {
+ println!(
+ "WARNING: The used version of LLDB (350) has a \
+ known issue that breaks debuginfo tests. See \
+ issue #32520 for more information. Skipping all \
+ LLDB-based tests!",
+ );
+ return None;
+ }
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
+}
+
+pub fn test_opts(config: &Config) -> test::TestOpts {
+ if env::var("RUST_TEST_NOCAPTURE").is_ok() {
+ eprintln!(
+ "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
+ Use the `--nocapture` flag instead."
+ );
+ }
+
+ test::TestOpts {
+ exclude_should_panic: false,
+ filters: config.filters.clone(),
+ filter_exact: config.filter_exact,
+ run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
+ format: config.format,
+ logfile: config.logfile.clone(),
+ run_tests: true,
+ bench_benchmarks: true,
+ nocapture: config.nocapture,
+ color: config.color,
+ shuffle: false,
+ shuffle_seed: None,
+ test_threads: None,
+ skip: config.skip.clone(),
+ list: false,
+ options: test::Options::new(),
+ time_options: None,
+ force_run_in_process: false,
+ fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
+ }
+}
+
+pub fn make_tests(
+ config: Arc<Config>,
+ tests: &mut Vec<test::TestDescAndFn>,
+ found_paths: &mut BTreeSet<PathBuf>,
+) {
+ debug!("making tests from {:?}", config.src_base.display());
+ let inputs = common_inputs_stamp(&config);
+ let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
+ panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
+ });
+
+ let cache = HeadersCache::load(&config);
+ let mut poisoned = false;
+ collect_tests_from_dir(
+ config.clone(),
+ &cache,
+ &config.src_base,
+ &PathBuf::new(),
+ &inputs,
+ tests,
+ found_paths,
+ &modified_tests,
+ &mut poisoned,
+ )
+ .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
+
+ if poisoned {
+ eprintln!();
+ panic!("there are errors in 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/rust_types.py",
+ "src/etc/gdb_load_rust_pretty_printers.py",
+ "src/etc/gdb_lookup.py",
+ "src/etc/gdb_providers.py",
+ "src/etc/lldb_batchmode.py",
+ "src/etc/lldb_lookup.py",
+ "src/etc/lldb_providers.py",
+ ];
+ for file in &pretty_printer_files {
+ let path = rust_src_dir.join(file);
+ stamp.add_path(&path);
+ }
+
+ stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
+
+ 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 modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
+ if !config.only_modified {
+ return Ok(vec![]);
+ }
+ let files =
+ get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
+ // Add new test cases to the list, it will be convenient in daily development.
+ let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
+
+ let all_paths = [&files[..], &untracked_files[..]].concat();
+ let full_paths = {
+ let mut full_paths: Vec<PathBuf> = all_paths
+ .into_iter()
+ .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
+ .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
+ .collect();
+ full_paths.dedup();
+ full_paths.sort_unstable();
+ full_paths
+ };
+ Ok(full_paths)
+}
+
+fn collect_tests_from_dir(
+ config: Arc<Config>,
+ cache: &HeadersCache,
+ dir: &Path,
+ relative_dir_path: &Path,
+ inputs: &Stamp,
+ tests: &mut Vec<test::TestDescAndFn>,
+ found_paths: &mut BTreeSet<PathBuf>,
+ modified_tests: &Vec<PathBuf>,
+ poisoned: &mut bool,
+) -> io::Result<()> {
+ // Ignore directories that contain a file named `compiletest-ignore-dir`.
+ if dir.join("compiletest-ignore-dir").exists() {
+ return Ok(());
+ }
+
+ if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
+ let paths = TestPaths {
+ file: dir.to_path_buf(),
+ relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
+ };
+ tests.extend(make_test(config, cache, &paths, inputs, poisoned));
+ return Ok(());
+ }
+
+ // If we find a test foo/bar.rs, we have to build the
+ // output directory `$build/foo` so we can write
+ // `$build/foo/bar` into it. We do this *now* in this
+ // sequential loop because otherwise, if we do it in the
+ // tests themselves, they race for the privilege of
+ // creating the directories and sometimes fail randomly.
+ let build_dir = output_relative_path(&config, relative_dir_path);
+ fs::create_dir_all(&build_dir).unwrap();
+
+ // Add each `.rs` file as a test, and recurse further on any
+ // subdirectories we find, except for `aux` directories.
+ for file in fs::read_dir(dir)? {
+ let file = file?;
+ let file_path = file.path();
+ let file_name = file.file_name();
+ if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
+ debug!("found test file: {:?}", file_path.display());
+ let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
+ found_paths.insert(rel_test_path);
+ let paths =
+ TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
+
+ tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
+ } 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.clone(),
+ cache,
+ &file_path,
+ &relative_file_path,
+ inputs,
+ tests,
+ found_paths,
+ modified_tests,
+ poisoned,
+ )?;
+ }
+ } else {
+ debug!("found other file/directory: {:?}", file_path.display());
+ }
+ }
+ Ok(())
+}
+
+/// Returns true if `file_name` looks like a proper test file name.
+pub fn is_test(file_name: &OsString) -> bool {
+ let file_name = file_name.to_str().unwrap();
+
+ if !file_name.ends_with(".rs") {
+ return false;
+ }
+
+ // `.`, `#`, and `~` are common temp-file prefixes.
+ let invalid_prefixes = &[".", "#", "~"];
+ !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
+}
+
+fn make_test(
+ config: Arc<Config>,
+ cache: &HeadersCache,
+ testpaths: &TestPaths,
+ inputs: &Stamp,
+ poisoned: &mut bool,
+) -> Vec<test::TestDescAndFn> {
+ let test_path = if config.mode == Mode::RunMake {
+ // Parse directives in the Makefile
+ testpaths.file.join("Makefile")
+ } else {
+ PathBuf::from(&testpaths.file)
+ };
+ let early_props = EarlyProps::from_file(&config, &test_path);
+
+ // Incremental tests are special, they inherently cannot be run in parallel.
+ // `runtest::run` will be responsible for iterating over revisions.
+ let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
+ vec![None]
+ } else {
+ early_props.revisions.iter().map(Some).collect()
+ };
+
+ revisions
+ .into_iter()
+ .map(|revision| {
+ let src_file =
+ std::fs::File::open(&test_path).expect("open test file to parse ignores");
+ let cfg = revision.map(|v| &**v);
+ let test_name = crate::make_test_name(&config, testpaths, revision);
+ let mut desc = make_test_description(
+ &config, cache, test_name, &test_path, src_file, cfg, poisoned,
+ );
+ // Ignore tests that already run and are up to date with respect to inputs.
+ if !config.force_rerun {
+ desc.ignore |= is_up_to_date(
+ &config,
+ testpaths,
+ &early_props,
+ revision.map(|s| s.as_str()),
+ inputs,
+ );
+ }
+ test::TestDescAndFn {
+ desc,
+ testfn: make_test_closure(config.clone(), testpaths, revision),
+ }
+ })
+ .collect()
+}
+
+fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+ output_base_dir(config, testpaths, revision).join("stamp")
+}
+
+fn files_related_to_test(
+ config: &Config,
+ testpaths: &TestPaths,
+ props: &EarlyProps,
+ revision: Option<&str>,
+) -> Vec<PathBuf> {
+ let mut related = vec![];
+
+ if testpaths.file.is_dir() {
+ // run-make tests use their individual directory
+ for entry in WalkDir::new(&testpaths.file) {
+ let path = entry.unwrap().into_path();
+ if path.is_file() {
+ related.push(path);
+ }
+ }
+ } else {
+ related.push(testpaths.file.clone());
+ }
+
+ for aux in &props.aux {
+ let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
+ related.push(path);
+ }
+
+ // UI test files.
+ for extension in UI_EXTENSIONS {
+ let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
+ related.push(path);
+ }
+
+ related
+}
+
+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 false,
+ };
+ let expected_hash = runtest::compute_stamp_hash(config);
+ if contents != expected_hash {
+ return false;
+ }
+
+ // Check timestamps.
+ let mut inputs = inputs.clone();
+ for path in files_related_to_test(config, testpaths, props, revision) {
+ inputs.add_path(&path);
+ }
+
+ inputs < Stamp::from_path(&stamp_name)
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Stamp {
+ time: SystemTime,
+}
+
+impl Stamp {
+ 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);
+ self.time = self.time.max(modified);
+ }
+
+ 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);
+ }
+ }
+ }
+}
+
+fn make_test_name(
+ config: &Config,
+ testpaths: &TestPaths,
+ revision: Option<&String>,
+) -> test::TestName {
+ // Print the name of the file, relative to the repository root.
+ // `src_base` looks like `/path/to/rust/tests/ui`
+ let root_directory = config.src_base.parent().unwrap().parent().unwrap();
+ let path = testpaths.file.strip_prefix(root_directory).unwrap();
+ let debugger = match config.debugger {
+ Some(d) => format!("-{}", d),
+ None => String::new(),
+ };
+ let mode_suffix = match config.compare_mode {
+ Some(ref mode) => format!(" ({})", mode.to_str()),
+ None => String::new(),
+ };
+
+ test::DynTestName(format!(
+ "[{}{}{}] {}{}",
+ config.mode,
+ debugger,
+ mode_suffix,
+ path.display(),
+ revision.map_or("".to_string(), |rev| format!("#{}", rev))
+ ))
+}
+
+fn make_test_closure(
+ config: Arc<Config>,
+ testpaths: &TestPaths,
+ revision: Option<&String>,
+) -> test::TestFn {
+ let config = config.clone();
+ let testpaths = testpaths.clone();
+ let revision = revision.cloned();
+ test::DynTestFn(Box::new(move || {
+ runtest::run(config, &testpaths, revision.as_deref());
+ Ok(())
+ }))
+}
+
+/// Returns `true` if the given target is an Android target for the
+/// purposes of GDB testing.
+fn is_android_gdb_target(target: &str) -> bool {
+ matches!(
+ &target[..],
+ "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
+ )
+}
+
+/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
+fn is_pc_windows_msvc_target(target: &str) -> bool {
+ target.ends_with("-pc-windows-msvc")
+}
+
+fn find_cdb(target: &str) -> Option<OsString> {
+ if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
+ return None;
+ }
+
+ let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
+ let cdb_arch = if cfg!(target_arch = "x86") {
+ "x86"
+ } else if cfg!(target_arch = "x86_64") {
+ "x64"
+ } else if cfg!(target_arch = "aarch64") {
+ "arm64"
+ } else if cfg!(target_arch = "arm") {
+ "arm"
+ } else {
+ return None; // No compatible CDB.exe in the Windows 10 SDK
+ };
+
+ let mut path = PathBuf::new();
+ path.push(pf86);
+ path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
+ path.push(cdb_arch);
+ path.push(r"cdb.exe");
+
+ if !path.exists() {
+ return None;
+ }
+
+ Some(path.into_os_string())
+}
+
+/// Returns Path to CDB
+fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
+ let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
+
+ let mut version = None;
+ if let Some(cdb) = cdb.as_ref() {
+ if let Ok(output) = Command::new(cdb).arg("/version").output() {
+ if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+ version = extract_cdb_version(&first_line);
+ }
+ }
+ }
+
+ (cdb, version)
+}
+
+fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
+ // Example full_version_line: "cdb version 10.0.18362.1"
+ let version = full_version_line.rsplit(' ').next()?;
+ let mut components = version.split('.');
+ let major: u16 = components.next().unwrap().parse().unwrap();
+ let minor: u16 = components.next().unwrap().parse().unwrap();
+ let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
+ let build: u16 = components.next().unwrap_or("0").parse().unwrap();
+ Some([major, minor, patch, build])
+}
+
+/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
+fn analyze_gdb(
+ gdb: Option<String>,
+ target: &str,
+ android_cross_path: &PathBuf,
+) -> (Option<String>, Option<u32>, bool) {
+ #[cfg(not(windows))]
+ const GDB_FALLBACK: &str = "gdb";
+ #[cfg(windows)]
+ const GDB_FALLBACK: &str = "gdb.exe";
+
+ const MIN_GDB_WITH_RUST: u32 = 7011010;
+
+ let fallback_gdb = || {
+ if is_android_gdb_target(target) {
+ let mut gdb_path = match android_cross_path.to_str() {
+ Some(x) => x.to_owned(),
+ None => panic!("cannot find android cross path"),
+ };
+ gdb_path.push_str("/bin/gdb");
+ gdb_path
+ } else {
+ GDB_FALLBACK.to_owned()
+ }
+ };
+
+ let gdb = match gdb {
+ None => fallback_gdb(),
+ Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
+ Some(ref s) => s.to_owned(),
+ };
+
+ let mut version_line = None;
+ if let Ok(output) = Command::new(&gdb).arg("--version").output() {
+ if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+ version_line = Some(first_line.to_string());
+ }
+ }
+
+ let version = match version_line {
+ Some(line) => extract_gdb_version(&line),
+ None => return (None, None, false),
+ };
+
+ let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
+
+ (Some(gdb), version, gdb_native_rust)
+}
+
+fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
+ let full_version_line = full_version_line.trim();
+
+ // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
+ // of the ? sections being optional
+
+ // We will parse up to 3 digits for each component, ignoring the date
+
+ // We skip text in parentheses. This avoids accidentally parsing
+ // the openSUSE version, which looks like:
+ // GNU gdb (GDB; openSUSE Leap 15.0) 8.1
+ // This particular form is documented in the GNU coding standards:
+ // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
+
+ let unbracketed_part = full_version_line.split('[').next().unwrap();
+ let mut splits = unbracketed_part.trim_end().rsplit(' ');
+ let version_string = splits.next().unwrap();
+
+ let mut splits = version_string.split('.');
+ let major = splits.next().unwrap();
+ let minor = splits.next().unwrap();
+ let patch = splits.next();
+
+ let major: u32 = major.parse().unwrap();
+ let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
+ None => {
+ let minor = minor.parse().unwrap();
+ let patch: u32 = match patch {
+ Some(patch) => match patch.find(not_a_digit) {
+ None => patch.parse().unwrap(),
+ Some(idx) if idx > 3 => 0,
+ Some(idx) => patch[..idx].parse().unwrap(),
+ },
+ None => 0,
+ };
+ (minor, patch)
+ }
+ // There is no patch version after minor-date (e.g. "4-2012").
+ Some(idx) => {
+ let minor = minor[..idx].parse().unwrap();
+ (minor, 0)
+ }
+ };
+
+ Some(((major * 1000) + minor) * 1000 + patch)
+}
+
+/// Returns (LLDB version, LLDB is rust-enabled)
+fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
+ // Extract the major LLDB version from the given version string.
+ // LLDB version strings are different for Apple and non-Apple platforms.
+ // The Apple variant looks like this:
+ //
+ // LLDB-179.5 (older versions)
+ // lldb-300.2.51 (new versions)
+ //
+ // We are only interested in the major version number, so this function
+ // will return `Some(179)` and `Some(300)` respectively.
+ //
+ // Upstream versions look like:
+ // lldb version 6.0.1
+ //
+ // There doesn't seem to be a way to correlate the Apple version
+ // with the upstream version, and since the tests were originally
+ // written against Apple versions, we make a fake Apple version by
+ // multiplying the first number by 100. This is a hack, but
+ // normally fine because the only non-Apple version we test is
+ // rust-enabled.
+
+ let full_version_line = full_version_line.trim();
+
+ if let Some(apple_ver) =
+ full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
+ {
+ if let Some(idx) = apple_ver.find(not_a_digit) {
+ let version: u32 = apple_ver[..idx].parse().unwrap();
+ return Some((version, full_version_line.contains("rust-enabled")));
+ }
+ } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
+ if let Some(idx) = lldb_ver.find(not_a_digit) {
+ let version: u32 = lldb_ver[..idx].parse().ok()?;
+ return Some((version * 100, full_version_line.contains("rust-enabled")));
+ }
+ }
+ None
+}
+
+fn not_a_digit(c: char) -> bool {
+ !c.is_digit(10)
+}
+
+fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
+ let mut collisions = Vec::new();
+ for path in found_paths {
+ for ancestor in path.ancestors().skip(1) {
+ if found_paths.contains(ancestor) {
+ collisions.push((path, ancestor.clone()));
+ }
+ }
+ }
+ if !collisions.is_empty() {
+ let collisions: String = collisions
+ .into_iter()
+ .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
+ .collect();
+ panic!(
+ "{collisions}\n\
+ Tests cannot have overlapping names. Make sure they use unique prefixes."
+ );
+ }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index c4bef99..34d4855 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,45 +1,6 @@
-#![crate_name = "compiletest"]
-// The `test` crate is the only unstable feature
-// allowed here, just to share similar code.
-#![feature(test)]
+use std::{env, sync::Arc};
-extern crate test;
-
-use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
-use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
-use crate::util::logv;
-use build_helper::git::{get_git_modified_files, get_git_untracked_files};
-use core::panic;
-use getopts::Options;
-use lazycell::AtomicLazyCell;
-use std::collections::BTreeSet;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, ErrorKind};
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-use std::time::SystemTime;
-use std::{env, vec};
-use test::ColorConfig;
-use tracing::*;
-use walkdir::WalkDir;
-
-use self::header::{make_test_description, EarlyProps};
-use crate::header::HeadersCache;
-use std::sync::Arc;
-
-#[cfg(test)]
-mod tests;
-
-pub mod common;
-pub mod compute_diff;
-pub mod errors;
-pub mod header;
-mod json;
-mod raise_fd_limit;
-mod read2;
-pub mod runtest;
-pub mod util;
+use compiletest::{common::Mode, log_config, parse_config, run_tests};
fn main() {
tracing_subscriber::fmt::init();
@@ -57,1097 +18,3 @@
log_config(&config);
run_tests(config);
}
-
-pub fn parse_config(args: Vec<String>) -> Config {
- let mut opts = Options::new();
- opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
- .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
- .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
- .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
- .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
- .reqopt("", "python", "path to python to use for doc tests", "PATH")
- .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
- .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
- .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
- .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
- .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
- .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
- .reqopt("", "src-base", "directory to scan for test files", "PATH")
- .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
- .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
- .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
- .reqopt(
- "",
- "mode",
- "which sort of compile tests to run",
- "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
- | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
- )
- .reqopt(
- "",
- "suite",
- "which suite of compile tests to run. used for nicer error reporting.",
- "SUITE",
- )
- .optopt(
- "",
- "pass",
- "force {check,build,run}-pass tests to this mode.",
- "check | build | run",
- )
- .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
- .optflag("", "ignored", "run tests marked as ignored")
- .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
- .optflag("", "exact", "filters match exactly")
- .optopt(
- "",
- "runtool",
- "supervisor program to run tests under \
- (eg. emulator, valgrind)",
- "PROGRAM",
- )
- .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
- .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
- .optflag("", "optimize-tests", "run tests with optimizations enabled")
- .optflag("", "verbose", "run tests verbosely, showing all output")
- .optflag(
- "",
- "bless",
- "overwrite stderr/stdout files instead of complaining about a mismatch",
- )
- .optflag("", "quiet", "print one character per test instead of one line")
- .optopt("", "color", "coloring: auto, always, never", "WHEN")
- .optflag("", "json", "emit json output instead of plaintext output")
- .optopt("", "logfile", "file to log test execution to", "FILE")
- .optopt("", "target", "the target to build for", "TARGET")
- .optopt("", "host", "the host to build for", "HOST")
- .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
- .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
- .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
- .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
- .optflag("", "system-llvm", "is LLVM the system LLVM")
- .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
- .optopt("", "adb-path", "path to the android debugger", "PATH")
- .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
- .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
- .reqopt("", "cc", "path to a C compiler", "PATH")
- .reqopt("", "cxx", "path to a C++ compiler", "PATH")
- .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
- .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
- .optopt("", "ar", "path to an archiver", "PATH")
- .optopt("", "target-linker", "path to a linker for the target", "PATH")
- .optopt("", "host-linker", "path to a linker for the host", "PATH")
- .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
- .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
- .optopt("", "nodejs", "the name of nodejs", "PATH")
- .optopt("", "npm", "the name of npm", "PATH")
- .optopt("", "remote-test-client", "path to the remote test client", "PATH")
- .optopt(
- "",
- "compare-mode",
- "mode describing what file the actual ui output will be compared to",
- "COMPARE MODE",
- )
- .optflag(
- "",
- "rustfix-coverage",
- "enable this to generate a Rustfix coverage file, which is saved in \
- `./<build_base>/rustfix_missing_coverage.txt`",
- )
- .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
- .optflag("", "only-modified", "only run tests that result been modified")
- .optflag("", "nocapture", "")
- .optflag("h", "help", "show this message")
- .reqopt("", "channel", "current Rust channel", "CHANNEL")
- .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
- .optopt("", "edition", "default Rust edition", "EDITION");
-
- let (argv0, args_) = args.split_first().unwrap();
- if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
- let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
- println!("{}", opts.usage(&message));
- println!();
- panic!()
- }
-
- let matches = &match opts.parse(args_) {
- Ok(m) => m,
- Err(f) => panic!("{:?}", f),
- };
-
- if matches.opt_present("h") || matches.opt_present("help") {
- let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
- println!("{}", opts.usage(&message));
- println!();
- panic!()
- }
-
- fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
- match m.opt_str(nm) {
- Some(s) => PathBuf::from(&s),
- None => panic!("no option (=path) found for {}", nm),
- }
- }
-
- fn make_absolute(path: PathBuf) -> PathBuf {
- if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
- }
-
- let target = opt_str2(matches.opt_str("target"));
- let android_cross_path = opt_path(matches, "android-cross-path");
- let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
- let (gdb, gdb_version, gdb_native_rust) =
- analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
- let (lldb_version, lldb_native_rust) = matches
- .opt_str("lldb-version")
- .as_deref()
- .and_then(extract_lldb_version)
- .map(|(v, b)| (Some(v), b))
- .unwrap_or((None, false));
- let color = match matches.opt_str("color").as_deref() {
- Some("auto") | None => ColorConfig::AutoColor,
- Some("always") => ColorConfig::AlwaysColor,
- Some("never") => ColorConfig::NeverColor,
- Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
- };
- let llvm_version =
- matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
- || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
- );
-
- let src_base = opt_path(matches, "src-base");
- let run_ignored = matches.opt_present("ignored");
- let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
- let has_tidy = if mode == Mode::Rustdoc {
- Command::new("tidy")
- .arg("--version")
- .stdout(Stdio::null())
- .status()
- .map_or(false, |status| status.success())
- } else {
- // Avoid spawning an external command when we know tidy won't be used.
- false
- };
- Config {
- bless: matches.opt_present("bless"),
- compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
- run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
- rustc_path: opt_path(matches, "rustc-path"),
- rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
- rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
- python: matches.opt_str("python").unwrap(),
- jsondocck_path: matches.opt_str("jsondocck-path"),
- jsondoclint_path: matches.opt_str("jsondoclint-path"),
- valgrind_path: matches.opt_str("valgrind-path"),
- force_valgrind: matches.opt_present("force-valgrind"),
- run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
- llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
- llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
- src_base,
- build_base: opt_path(matches, "build-base"),
- sysroot_base: opt_path(matches, "sysroot-base"),
- stage_id: matches.opt_str("stage-id").unwrap(),
- mode,
- suite: matches.opt_str("suite").unwrap(),
- debugger: None,
- run_ignored,
- filters: matches.free.clone(),
- skip: matches.opt_strs("skip"),
- filter_exact: matches.opt_present("exact"),
- force_pass_mode: matches.opt_str("pass").map(|mode| {
- mode.parse::<PassMode>()
- .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
- }),
- run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
- "auto" => None,
- "always" => Some(true),
- "never" => Some(false),
- _ => panic!("unknown `--run` option `{}` given", mode),
- }),
- logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
- runtool: matches.opt_str("runtool"),
- host_rustcflags: matches.opt_strs("host-rustcflags"),
- target_rustcflags: matches.opt_strs("target-rustcflags"),
- optimize_tests: matches.opt_present("optimize-tests"),
- target,
- host: opt_str2(matches.opt_str("host")),
- cdb,
- cdb_version,
- gdb,
- gdb_version,
- gdb_native_rust,
- lldb_version,
- lldb_native_rust,
- llvm_version,
- system_llvm: matches.opt_present("system-llvm"),
- android_cross_path,
- adb_path: opt_str2(matches.opt_str("adb-path")),
- adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
- adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
- && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
- && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
- lldb_python_dir: matches.opt_str("lldb-python-dir"),
- verbose: matches.opt_present("verbose"),
- format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
- (true, true) => panic!("--quiet and --json are incompatible"),
- (true, false) => test::OutputFormat::Terse,
- (false, true) => test::OutputFormat::Json,
- (false, false) => test::OutputFormat::Pretty,
- },
- only_modified: matches.opt_present("only-modified"),
- color,
- remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
- compare_mode: matches
- .opt_str("compare-mode")
- .map(|s| s.parse().expect("invalid --compare-mode provided")),
- rustfix_coverage: matches.opt_present("rustfix-coverage"),
- has_tidy,
- channel: matches.opt_str("channel").unwrap(),
- git_hash: matches.opt_present("git-hash"),
- edition: matches.opt_str("edition"),
-
- cc: matches.opt_str("cc").unwrap(),
- cxx: matches.opt_str("cxx").unwrap(),
- cflags: matches.opt_str("cflags").unwrap(),
- cxxflags: matches.opt_str("cxxflags").unwrap(),
- ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
- target_linker: matches.opt_str("target-linker"),
- host_linker: matches.opt_str("host-linker"),
- llvm_components: matches.opt_str("llvm-components").unwrap(),
- nodejs: matches.opt_str("nodejs"),
- npm: matches.opt_str("npm"),
-
- force_rerun: matches.opt_present("force-rerun"),
-
- target_cfgs: AtomicLazyCell::new(),
-
- nocapture: matches.opt_present("nocapture"),
- }
-}
-
-pub fn log_config(config: &Config) {
- let c = config;
- logv(c, "configuration:".to_string());
- logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
- logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
- logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
- logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
- logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
- logv(c, format!("src_base: {:?}", config.src_base.display()));
- logv(c, format!("build_base: {:?}", config.build_base.display()));
- logv(c, format!("stage_id: {}", config.stage_id));
- logv(c, format!("mode: {}", config.mode));
- logv(c, format!("run_ignored: {}", config.run_ignored));
- logv(c, format!("filters: {:?}", config.filters));
- logv(c, format!("skip: {:?}", config.skip));
- logv(c, format!("filter_exact: {}", config.filter_exact));
- logv(
- c,
- format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
- );
- logv(c, format!("runtool: {}", opt_str(&config.runtool)));
- logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
- logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
- logv(c, format!("target: {}", config.target));
- logv(c, format!("host: {}", config.host));
- logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
- logv(c, format!("adb_path: {:?}", config.adb_path));
- logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
- logv(c, format!("adb_device_status: {}", config.adb_device_status));
- logv(c, format!("ar: {}", config.ar));
- logv(c, format!("target-linker: {:?}", config.target_linker));
- logv(c, format!("host-linker: {:?}", config.host_linker));
- logv(c, format!("verbose: {}", config.verbose));
- logv(c, format!("format: {:?}", config.format));
- logv(c, "\n".to_string());
-}
-
-pub fn opt_str(maybestr: &Option<String>) -> &str {
- match *maybestr {
- None => "(none)",
- Some(ref s) => s,
- }
-}
-
-pub fn opt_str2(maybestr: Option<String>) -> String {
- match maybestr {
- None => "(none)".to_owned(),
- Some(s) => s,
- }
-}
-
-pub fn run_tests(config: Arc<Config>) {
- // If we want to collect rustfix coverage information,
- // we first make sure that the coverage file does not exist.
- // It will be created later on.
- if config.rustfix_coverage {
- let mut coverage_file_path = config.build_base.clone();
- coverage_file_path.push("rustfix_missing_coverage.txt");
- if coverage_file_path.exists() {
- if let Err(e) = fs::remove_file(&coverage_file_path) {
- panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
- }
- }
- }
-
- // sadly osx needs some file descriptor limits raised for running tests in
- // parallel (especially when we have lots and lots of child processes).
- // For context, see #8904
- unsafe {
- raise_fd_limit::raise_fd_limit();
- }
- // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
- // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
- env::set_var("__COMPAT_LAYER", "RunAsInvoker");
-
- // Let tests know which target they're running as
- env::set_var("TARGET", &config.target);
-
- let opts = test_opts(&config);
-
- let mut configs = Vec::new();
- if let Mode::DebugInfo = config.mode {
- // Debugging emscripten code doesn't make sense today
- if !config.target.contains("emscripten") {
- configs.extend(configure_cdb(&config));
- configs.extend(configure_gdb(&config));
- configs.extend(configure_lldb(&config));
- }
- } else {
- configs.push(config.clone());
- };
-
- let mut tests = Vec::new();
- for c in configs {
- let mut found_paths = BTreeSet::new();
- make_tests(c, &mut tests, &mut found_paths);
- check_overlapping_tests(&found_paths);
- }
-
- tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
-
- let res = test::run_tests_console(&opts, tests);
- match res {
- Ok(true) => {}
- Ok(false) => {
- // We want to report that the tests failed, but we also want to give
- // some indication of just what tests we were running. Especially on
- // CI, where there can be cross-compiled tests for a lot of
- // architectures, without this critical information it can be quite
- // easy to miss which tests failed, and as such fail to reproduce
- // the failure locally.
-
- println!(
- "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
- config.suite,
- config
- .compare_mode
- .as_ref()
- .map(|c| format!(" compare_mode={:?}", c))
- .unwrap_or_default(),
- config.mode,
- config.host,
- config.target
- );
-
- std::process::exit(1);
- }
- Err(e) => {
- // We don't know if tests passed or not, but if there was an error
- // during testing we don't want to just succeed (we may not have
- // tested something), so fail.
- //
- // This should realistically "never" happen, so don't try to make
- // this a pretty error message.
- panic!("I/O failure during tests: {:?}", e);
- }
- }
-}
-
-fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
- config.cdb.as_ref()?;
-
- Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
-}
-
-fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
- config.gdb_version?;
-
- if config.matches_env("msvc") {
- return None;
- }
-
- if config.remote_test_client.is_some() && !config.target.contains("android") {
- println!(
- "WARNING: debuginfo tests are not available when \
- testing with remote"
- );
- return None;
- }
-
- if config.target.contains("android") {
- println!(
- "{} debug-info test uses tcp 5039 port.\
- please reserve it",
- config.target
- );
-
- // android debug-info test uses remote debugger so, we test 1 thread
- // at once as they're all sharing the same TCP port to communicate
- // over.
- //
- // we should figure out how to lift this restriction! (run them all
- // on different ports allocated dynamically).
- env::set_var("RUST_TEST_THREADS", "1");
- }
-
- Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
-}
-
-fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
- config.lldb_python_dir.as_ref()?;
-
- if let Some(350) = config.lldb_version {
- println!(
- "WARNING: The used version of LLDB (350) has a \
- known issue that breaks debuginfo tests. See \
- issue #32520 for more information. Skipping all \
- LLDB-based tests!",
- );
- return None;
- }
-
- Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
-}
-
-pub fn test_opts(config: &Config) -> test::TestOpts {
- if env::var("RUST_TEST_NOCAPTURE").is_ok() {
- eprintln!(
- "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
- Use the `--nocapture` flag instead."
- );
- }
-
- test::TestOpts {
- exclude_should_panic: false,
- filters: config.filters.clone(),
- filter_exact: config.filter_exact,
- run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
- format: config.format,
- logfile: config.logfile.clone(),
- run_tests: true,
- bench_benchmarks: true,
- nocapture: config.nocapture,
- color: config.color,
- shuffle: false,
- shuffle_seed: None,
- test_threads: None,
- skip: config.skip.clone(),
- list: false,
- options: test::Options::new(),
- time_options: None,
- force_run_in_process: false,
- fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
- }
-}
-
-pub fn make_tests(
- config: Arc<Config>,
- tests: &mut Vec<test::TestDescAndFn>,
- found_paths: &mut BTreeSet<PathBuf>,
-) {
- debug!("making tests from {:?}", config.src_base.display());
- let inputs = common_inputs_stamp(&config);
- let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
- panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
- });
-
- let cache = HeadersCache::load(&config);
- let mut poisoned = false;
- collect_tests_from_dir(
- config.clone(),
- &cache,
- &config.src_base,
- &PathBuf::new(),
- &inputs,
- tests,
- found_paths,
- &modified_tests,
- &mut poisoned,
- )
- .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
-
- if poisoned {
- eprintln!();
- panic!("there are errors in 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/rust_types.py",
- "src/etc/gdb_load_rust_pretty_printers.py",
- "src/etc/gdb_lookup.py",
- "src/etc/gdb_providers.py",
- "src/etc/lldb_batchmode.py",
- "src/etc/lldb_lookup.py",
- "src/etc/lldb_providers.py",
- ];
- for file in &pretty_printer_files {
- let path = rust_src_dir.join(file);
- stamp.add_path(&path);
- }
-
- stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
-
- 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 modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
- if !config.only_modified {
- return Ok(vec![]);
- }
- let files =
- get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
- // Add new test cases to the list, it will be convenient in daily development.
- let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
-
- let all_paths = [&files[..], &untracked_files[..]].concat();
- let full_paths = {
- let mut full_paths: Vec<PathBuf> = all_paths
- .into_iter()
- .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
- .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
- .collect();
- full_paths.dedup();
- full_paths.sort_unstable();
- full_paths
- };
- Ok(full_paths)
-}
-
-fn collect_tests_from_dir(
- config: Arc<Config>,
- cache: &HeadersCache,
- dir: &Path,
- relative_dir_path: &Path,
- inputs: &Stamp,
- tests: &mut Vec<test::TestDescAndFn>,
- found_paths: &mut BTreeSet<PathBuf>,
- modified_tests: &Vec<PathBuf>,
- poisoned: &mut bool,
-) -> io::Result<()> {
- // Ignore directories that contain a file named `compiletest-ignore-dir`.
- if dir.join("compiletest-ignore-dir").exists() {
- return Ok(());
- }
-
- if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
- let paths = TestPaths {
- file: dir.to_path_buf(),
- relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
- };
- tests.extend(make_test(config, cache, &paths, inputs, poisoned));
- return Ok(());
- }
-
- // If we find a test foo/bar.rs, we have to build the
- // output directory `$build/foo` so we can write
- // `$build/foo/bar` into it. We do this *now* in this
- // sequential loop because otherwise, if we do it in the
- // tests themselves, they race for the privilege of
- // creating the directories and sometimes fail randomly.
- let build_dir = output_relative_path(&config, relative_dir_path);
- fs::create_dir_all(&build_dir).unwrap();
-
- // Add each `.rs` file as a test, and recurse further on any
- // subdirectories we find, except for `aux` directories.
- for file in fs::read_dir(dir)? {
- let file = file?;
- let file_path = file.path();
- let file_name = file.file_name();
- if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
- debug!("found test file: {:?}", file_path.display());
- let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
- found_paths.insert(rel_test_path);
- let paths =
- TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
-
- tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
- } 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.clone(),
- cache,
- &file_path,
- &relative_file_path,
- inputs,
- tests,
- found_paths,
- modified_tests,
- poisoned,
- )?;
- }
- } else {
- debug!("found other file/directory: {:?}", file_path.display());
- }
- }
- Ok(())
-}
-
-/// Returns true if `file_name` looks like a proper test file name.
-pub fn is_test(file_name: &OsString) -> bool {
- let file_name = file_name.to_str().unwrap();
-
- if !file_name.ends_with(".rs") {
- return false;
- }
-
- // `.`, `#`, and `~` are common temp-file prefixes.
- let invalid_prefixes = &[".", "#", "~"];
- !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
-}
-
-fn make_test(
- config: Arc<Config>,
- cache: &HeadersCache,
- testpaths: &TestPaths,
- inputs: &Stamp,
- poisoned: &mut bool,
-) -> Vec<test::TestDescAndFn> {
- let test_path = if config.mode == Mode::RunMake {
- // Parse directives in the Makefile
- testpaths.file.join("Makefile")
- } else {
- PathBuf::from(&testpaths.file)
- };
- let early_props = EarlyProps::from_file(&config, &test_path);
-
- // Incremental tests are special, they inherently cannot be run in parallel.
- // `runtest::run` will be responsible for iterating over revisions.
- let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
- vec![None]
- } else {
- early_props.revisions.iter().map(Some).collect()
- };
-
- revisions
- .into_iter()
- .map(|revision| {
- let src_file =
- std::fs::File::open(&test_path).expect("open test file to parse ignores");
- let cfg = revision.map(|v| &**v);
- let test_name = crate::make_test_name(&config, testpaths, revision);
- let mut desc = make_test_description(
- &config, cache, test_name, &test_path, src_file, cfg, poisoned,
- );
- // Ignore tests that already run and are up to date with respect to inputs.
- if !config.force_rerun {
- desc.ignore |= is_up_to_date(
- &config,
- testpaths,
- &early_props,
- revision.map(|s| s.as_str()),
- inputs,
- );
- }
- test::TestDescAndFn {
- desc,
- testfn: make_test_closure(config.clone(), testpaths, revision),
- }
- })
- .collect()
-}
-
-fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
- output_base_dir(config, testpaths, revision).join("stamp")
-}
-
-fn files_related_to_test(
- config: &Config,
- testpaths: &TestPaths,
- props: &EarlyProps,
- revision: Option<&str>,
-) -> Vec<PathBuf> {
- let mut related = vec![];
-
- if testpaths.file.is_dir() {
- // run-make tests use their individual directory
- for entry in WalkDir::new(&testpaths.file) {
- let path = entry.unwrap().into_path();
- if path.is_file() {
- related.push(path);
- }
- }
- } else {
- related.push(testpaths.file.clone());
- }
-
- for aux in &props.aux {
- let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
- related.push(path);
- }
-
- // UI test files.
- for extension in UI_EXTENSIONS {
- let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
- related.push(path);
- }
-
- related
-}
-
-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 false,
- };
- let expected_hash = runtest::compute_stamp_hash(config);
- if contents != expected_hash {
- return false;
- }
-
- // Check timestamps.
- let mut inputs = inputs.clone();
- for path in files_related_to_test(config, testpaths, props, revision) {
- inputs.add_path(&path);
- }
-
- inputs < Stamp::from_path(&stamp_name)
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-struct Stamp {
- time: SystemTime,
-}
-
-impl Stamp {
- 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);
- self.time = self.time.max(modified);
- }
-
- 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);
- }
- }
- }
-}
-
-fn make_test_name(
- config: &Config,
- testpaths: &TestPaths,
- revision: Option<&String>,
-) -> test::TestName {
- // Print the name of the file, relative to the repository root.
- // `src_base` looks like `/path/to/rust/tests/ui`
- let root_directory = config.src_base.parent().unwrap().parent().unwrap();
- let path = testpaths.file.strip_prefix(root_directory).unwrap();
- let debugger = match config.debugger {
- Some(d) => format!("-{}", d),
- None => String::new(),
- };
- let mode_suffix = match config.compare_mode {
- Some(ref mode) => format!(" ({})", mode.to_str()),
- None => String::new(),
- };
-
- test::DynTestName(format!(
- "[{}{}{}] {}{}",
- config.mode,
- debugger,
- mode_suffix,
- path.display(),
- revision.map_or("".to_string(), |rev| format!("#{}", rev))
- ))
-}
-
-fn make_test_closure(
- config: Arc<Config>,
- testpaths: &TestPaths,
- revision: Option<&String>,
-) -> test::TestFn {
- let config = config.clone();
- let testpaths = testpaths.clone();
- let revision = revision.cloned();
- test::DynTestFn(Box::new(move || {
- runtest::run(config, &testpaths, revision.as_deref());
- Ok(())
- }))
-}
-
-/// Returns `true` if the given target is an Android target for the
-/// purposes of GDB testing.
-fn is_android_gdb_target(target: &str) -> bool {
- matches!(
- &target[..],
- "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
- )
-}
-
-/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
-fn is_pc_windows_msvc_target(target: &str) -> bool {
- target.ends_with("-pc-windows-msvc")
-}
-
-fn find_cdb(target: &str) -> Option<OsString> {
- if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
- return None;
- }
-
- let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
- let cdb_arch = if cfg!(target_arch = "x86") {
- "x86"
- } else if cfg!(target_arch = "x86_64") {
- "x64"
- } else if cfg!(target_arch = "aarch64") {
- "arm64"
- } else if cfg!(target_arch = "arm") {
- "arm"
- } else {
- return None; // No compatible CDB.exe in the Windows 10 SDK
- };
-
- let mut path = PathBuf::new();
- path.push(pf86);
- path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
- path.push(cdb_arch);
- path.push(r"cdb.exe");
-
- if !path.exists() {
- return None;
- }
-
- Some(path.into_os_string())
-}
-
-/// Returns Path to CDB
-fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
- let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
-
- let mut version = None;
- if let Some(cdb) = cdb.as_ref() {
- if let Ok(output) = Command::new(cdb).arg("/version").output() {
- if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
- version = extract_cdb_version(&first_line);
- }
- }
- }
-
- (cdb, version)
-}
-
-fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
- // Example full_version_line: "cdb version 10.0.18362.1"
- let version = full_version_line.rsplit(' ').next()?;
- let mut components = version.split('.');
- let major: u16 = components.next().unwrap().parse().unwrap();
- let minor: u16 = components.next().unwrap().parse().unwrap();
- let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
- let build: u16 = components.next().unwrap_or("0").parse().unwrap();
- Some([major, minor, patch, build])
-}
-
-/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
-fn analyze_gdb(
- gdb: Option<String>,
- target: &str,
- android_cross_path: &PathBuf,
-) -> (Option<String>, Option<u32>, bool) {
- #[cfg(not(windows))]
- const GDB_FALLBACK: &str = "gdb";
- #[cfg(windows)]
- const GDB_FALLBACK: &str = "gdb.exe";
-
- const MIN_GDB_WITH_RUST: u32 = 7011010;
-
- let fallback_gdb = || {
- if is_android_gdb_target(target) {
- let mut gdb_path = match android_cross_path.to_str() {
- Some(x) => x.to_owned(),
- None => panic!("cannot find android cross path"),
- };
- gdb_path.push_str("/bin/gdb");
- gdb_path
- } else {
- GDB_FALLBACK.to_owned()
- }
- };
-
- let gdb = match gdb {
- None => fallback_gdb(),
- Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
- Some(ref s) => s.to_owned(),
- };
-
- let mut version_line = None;
- if let Ok(output) = Command::new(&gdb).arg("--version").output() {
- if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
- version_line = Some(first_line.to_string());
- }
- }
-
- let version = match version_line {
- Some(line) => extract_gdb_version(&line),
- None => return (None, None, false),
- };
-
- let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
-
- (Some(gdb), version, gdb_native_rust)
-}
-
-fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
- let full_version_line = full_version_line.trim();
-
- // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
- // of the ? sections being optional
-
- // We will parse up to 3 digits for each component, ignoring the date
-
- // We skip text in parentheses. This avoids accidentally parsing
- // the openSUSE version, which looks like:
- // GNU gdb (GDB; openSUSE Leap 15.0) 8.1
- // This particular form is documented in the GNU coding standards:
- // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
-
- let unbracketed_part = full_version_line.split('[').next().unwrap();
- let mut splits = unbracketed_part.trim_end().rsplit(' ');
- let version_string = splits.next().unwrap();
-
- let mut splits = version_string.split('.');
- let major = splits.next().unwrap();
- let minor = splits.next().unwrap();
- let patch = splits.next();
-
- let major: u32 = major.parse().unwrap();
- let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
- None => {
- let minor = minor.parse().unwrap();
- let patch: u32 = match patch {
- Some(patch) => match patch.find(not_a_digit) {
- None => patch.parse().unwrap(),
- Some(idx) if idx > 3 => 0,
- Some(idx) => patch[..idx].parse().unwrap(),
- },
- None => 0,
- };
- (minor, patch)
- }
- // There is no patch version after minor-date (e.g. "4-2012").
- Some(idx) => {
- let minor = minor[..idx].parse().unwrap();
- (minor, 0)
- }
- };
-
- Some(((major * 1000) + minor) * 1000 + patch)
-}
-
-/// Returns (LLDB version, LLDB is rust-enabled)
-fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
- // Extract the major LLDB version from the given version string.
- // LLDB version strings are different for Apple and non-Apple platforms.
- // The Apple variant looks like this:
- //
- // LLDB-179.5 (older versions)
- // lldb-300.2.51 (new versions)
- //
- // We are only interested in the major version number, so this function
- // will return `Some(179)` and `Some(300)` respectively.
- //
- // Upstream versions look like:
- // lldb version 6.0.1
- //
- // There doesn't seem to be a way to correlate the Apple version
- // with the upstream version, and since the tests were originally
- // written against Apple versions, we make a fake Apple version by
- // multiplying the first number by 100. This is a hack, but
- // normally fine because the only non-Apple version we test is
- // rust-enabled.
-
- let full_version_line = full_version_line.trim();
-
- if let Some(apple_ver) =
- full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
- {
- if let Some(idx) = apple_ver.find(not_a_digit) {
- let version: u32 = apple_ver[..idx].parse().unwrap();
- return Some((version, full_version_line.contains("rust-enabled")));
- }
- } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
- if let Some(idx) = lldb_ver.find(not_a_digit) {
- let version: u32 = lldb_ver[..idx].parse().ok()?;
- return Some((version * 100, full_version_line.contains("rust-enabled")));
- }
- }
- None
-}
-
-fn not_a_digit(c: char) -> bool {
- !c.is_digit(10)
-}
-
-fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
- let mut collisions = Vec::new();
- for path in found_paths {
- for ancestor in path.ancestors().skip(1) {
- if found_paths.contains(ancestor) {
- collisions.push((path, ancestor.clone()));
- }
- }
- }
- if !collisions.is_empty() {
- let collisions: String = collisions
- .into_iter()
- .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
- .collect();
- panic!(
- "{collisions}\n\
- Tests cannot have overlapping names. Make sure they use unique prefixes."
- );
- }
-}
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 29f518f..0ba7dad 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -651,6 +651,10 @@
/// Sets up the "extern statics" for this machine.
fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
+ // "__rust_no_alloc_shim_is_unstable"
+ let val = ImmTy::from_int(0, this.machine.layouts.u8);
+ Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
+
match this.tcx.sess.target.os.as_ref() {
"linux" => {
// "environ"
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index aa0794c..7436499 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -347,7 +347,6 @@
/// Emulates calling the internal __rust_* allocator functions
fn emulate_allocator(
&mut self,
- symbol: Symbol,
default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>,
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
let this = self.eval_context_mut();
@@ -359,11 +358,12 @@
match allocator_kind {
AllocatorKind::Global => {
- let (body, instance) = this
- .lookup_exported_symbol(symbol)?
- .expect("symbol should be present if there is a global allocator");
-
- Ok(EmulateByNameResult::MirBody(body, instance))
+ // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
+ // of this attribute. As such we have to call an exported Rust function,
+ // and not execute any Miri shim. Somewhat unintuitively doing so is done
+ // by returning `NotSupported`, which triggers the `lookup_exported_symbol`
+ // fallback case in `emulate_foreign_item`.
+ return Ok(EmulateByNameResult::NotSupported);
}
AllocatorKind::Default => {
default(this)?;
@@ -558,11 +558,13 @@
// Rust allocation
"__rust_alloc" | "miri_alloc" => {
- let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
- let size = this.read_target_usize(size)?;
- let align = this.read_target_usize(align)?;
-
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+ // Only call `check_shim` when `#[global_allocator]` isn't used. When that
+ // macro is used, we act like no shim exists, so that the exported function can run.
+ let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+ let size = this.read_target_usize(size)?;
+ let align = this.read_target_usize(align)?;
+
Self::check_alloc_request(size, align)?;
let memory_kind = match link_name.as_str() {
@@ -581,8 +583,7 @@
};
match link_name.as_str() {
- "__rust_alloc" =>
- return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
+ "__rust_alloc" => return this.emulate_allocator(default),
"miri_alloc" => {
default(this)?;
return Ok(EmulateByNameResult::NeedsJumping);
@@ -591,11 +592,13 @@
}
}
"__rust_alloc_zeroed" => {
- let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
- let size = this.read_target_usize(size)?;
- let align = this.read_target_usize(align)?;
+ return this.emulate_allocator(|this| {
+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
+ // default case.
+ let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+ let size = this.read_target_usize(size)?;
+ let align = this.read_target_usize(align)?;
- return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| {
Self::check_alloc_request(size, align)?;
let ptr = this.allocate_ptr(
@@ -614,12 +617,15 @@
});
}
"__rust_dealloc" | "miri_dealloc" => {
- let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
- let ptr = this.read_pointer(ptr)?;
- let old_size = this.read_target_usize(old_size)?;
- let align = this.read_target_usize(align)?;
-
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
+ // default case.
+ let [ptr, old_size, align] =
+ this.check_shim(abi, Abi::Rust, link_name, args)?;
+ let ptr = this.read_pointer(ptr)?;
+ let old_size = this.read_target_usize(old_size)?;
+ let align = this.read_target_usize(align)?;
+
let memory_kind = match link_name.as_str() {
"__rust_dealloc" => MiriMemoryKind::Rust,
"miri_dealloc" => MiriMemoryKind::Miri,
@@ -635,8 +641,9 @@
};
match link_name.as_str() {
- "__rust_dealloc" =>
- return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
+ "__rust_dealloc" => {
+ return this.emulate_allocator(default);
+ }
"miri_dealloc" => {
default(this)?;
return Ok(EmulateByNameResult::NeedsJumping);
@@ -645,15 +652,17 @@
}
}
"__rust_realloc" => {
- let [ptr, old_size, align, new_size] =
- this.check_shim(abi, Abi::Rust, link_name, args)?;
- let ptr = this.read_pointer(ptr)?;
- let old_size = this.read_target_usize(old_size)?;
- let align = this.read_target_usize(align)?;
- let new_size = this.read_target_usize(new_size)?;
- // No need to check old_size; we anyway check that they match the allocation.
+ return this.emulate_allocator(|this| {
+ // See the comment for `__rust_alloc` why `check_shim` is only called in the
+ // default case.
+ let [ptr, old_size, align, new_size] =
+ this.check_shim(abi, Abi::Rust, link_name, args)?;
+ let ptr = this.read_pointer(ptr)?;
+ let old_size = this.read_target_usize(old_size)?;
+ let align = this.read_target_usize(align)?;
+ let new_size = this.read_target_usize(new_size)?;
+ // No need to check old_size; we anyway check that they match the allocation.
- return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| {
Self::check_alloc_request(new_size, align)?;
let align = Align::from_bytes(align).unwrap();
diff --git a/src/tools/miri/tests/fail/memleak.stderr b/src/tools/miri/tests/fail/memleak.stderr
index 6d9b664..12bb944 100644
--- a/src/tools/miri/tests/fail/memleak.stderr
+++ b/src/tools/miri/tests/fail/memleak.stderr
@@ -1,8 +1,8 @@
error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here:
--> RUSTLIB/alloc/src/alloc.rs:LL:CC
|
-LL | unsafe { __rust_alloc(layout.size(), layout.align()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | __rust_alloc(layout.size(), layout.align())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
index 0e1146c..87c5f46 100644
--- a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
+++ b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
@@ -1,8 +1,8 @@
error: memory leaked: ALLOC (Rust heap, size: 16, align: 4), allocated here:
--> RUSTLIB/alloc/src/alloc.rs:LL:CC
|
-LL | unsafe { __rust_alloc(layout.size(), layout.align()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | __rust_alloc(layout.size(), layout.align())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
index 4979588..ec5f5f5 100644
--- a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
+++ b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
@@ -1,8 +1,8 @@
error: memory leaked: ALLOC (Rust heap, size: 32, align: 8), allocated here:
--> RUSTLIB/alloc/src/alloc.rs:LL:CC
|
-LL | unsafe { __rust_alloc(layout.size(), layout.align()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | __rust_alloc(layout.size(), layout.align())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
index 22ffa1b..b9199cf 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.rs
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -12,13 +12,13 @@
#[inline(always)]
fn has_cleanup() {
+ //~^ ERROR: panic in a function that cannot unwind
let _f = Foo;
panic!();
}
extern "C" fn panic_abort() {
has_cleanup();
- //~^ ERROR: panic in a function that cannot unwind
}
fn main() {
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index 8ce4bb7..d73e23a 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -6,15 +6,18 @@
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | / fn has_cleanup() {
+LL | |
LL | | let _f = Foo;
LL | | panic!();
LL | | }
| |_^ panic in a function that cannot unwind
-...
-LL | has_cleanup();
- | ------------- in this inlined function call
|
- = note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC
+ = note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
+note: inside `panic_abort`
+ --> $DIR/terminate-terminator.rs:LL:CC
+ |
+LL | has_cleanup();
+ | ^^^^^^^^^^^^^
note: inside `main`
--> $DIR/terminate-terminator.rs:LL:CC
|
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index af245aa..3258a2b 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -31,7 +31,7 @@
}
fn host_to_target_path(path: String) -> PathBuf {
- use std::ffi::{CStr, CString};
+ use std::ffi::{c_char, CStr, CString};
let path = CString::new(path).unwrap();
let mut out = Vec::with_capacity(1024);
diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml
new file mode 100644
index 0000000..f0c5b36
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rustdoc-gui-test"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+compiletest = { path = "../compiletest" }
+getopts = "0.2"
+walkdir = "2"
diff --git a/src/tools/rustdoc-gui-test/src/config.rs b/src/tools/rustdoc-gui-test/src/config.rs
new file mode 100644
index 0000000..dc4c56a
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/config.rs
@@ -0,0 +1,62 @@
+use getopts::Options;
+use std::{env, path::PathBuf};
+
+pub(crate) struct Config {
+ pub(crate) nodejs: PathBuf,
+ pub(crate) npm: PathBuf,
+ pub(crate) rust_src: PathBuf,
+ pub(crate) out_dir: PathBuf,
+ pub(crate) initial_cargo: PathBuf,
+ pub(crate) jobs: String,
+ pub(crate) test_args: Vec<PathBuf>,
+ pub(crate) goml_files: Vec<PathBuf>,
+ pub(crate) rustc: PathBuf,
+ pub(crate) rustdoc: PathBuf,
+ pub(crate) verbose: bool,
+}
+
+impl Config {
+ pub(crate) fn from_args(args: Vec<String>) -> Self {
+ let mut opts = Options::new();
+ opts.reqopt("", "nodejs", "absolute path of nodejs", "PATH")
+ .reqopt("", "npm", "absolute path of npm", "PATH")
+ .reqopt("", "out-dir", "output path of doc compilation", "PATH")
+ .reqopt("", "rust-src", "root source of the rust source", "PATH")
+ .reqopt(
+ "",
+ "initial-cargo",
+ "path to cargo to use for compiling tests/rustdoc-gui/src/*",
+ "PATH",
+ )
+ .reqopt("", "jobs", "jobs arg of browser-ui-test", "JOBS")
+ .optflag("", "verbose", "run tests verbosely, showing all output")
+ .optmulti("", "test-arg", "args for browser-ui-test", "FLAGS")
+ .optmulti("", "goml-file", "goml files for testing with browser-ui-test", "LIST");
+
+ let (argv0, args_) = args.split_first().unwrap();
+ if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ std::process::exit(1);
+ }
+
+ let matches = &match opts.parse(args_) {
+ Ok(m) => m,
+ Err(f) => panic!("{:?}", f),
+ };
+
+ Self {
+ nodejs: matches.opt_str("nodejs").map(PathBuf::from).expect("nodejs isn't available"),
+ npm: matches.opt_str("npm").map(PathBuf::from).expect("npm isn't available"),
+ rust_src: matches.opt_str("rust-src").map(PathBuf::from).unwrap(),
+ out_dir: matches.opt_str("out-dir").map(PathBuf::from).unwrap(),
+ initial_cargo: matches.opt_str("initial-cargo").map(PathBuf::from).unwrap(),
+ jobs: matches.opt_str("jobs").unwrap(),
+ goml_files: matches.opt_strs("goml-file").iter().map(PathBuf::from).collect(),
+ test_args: matches.opt_strs("test-arg").iter().map(PathBuf::from).collect(),
+ rustc: env::var("RUSTC").map(PathBuf::from).unwrap(),
+ rustdoc: env::var("RUSTDOC").map(PathBuf::from).unwrap(),
+ verbose: matches.opt_present("verbose"),
+ }
+ }
+}
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
new file mode 100644
index 0000000..8dc18df
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -0,0 +1,162 @@
+use compiletest::header::TestProps;
+use config::Config;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::sync::Arc;
+use std::{env, fs};
+
+mod config;
+
+fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> {
+ let mut command = Command::new(&npm);
+ command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
+ if global {
+ command.arg("--global");
+ }
+ let lines = command
+ .output()
+ .map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
+ .unwrap_or(String::new());
+ lines
+ .lines()
+ .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
+ .map(|v| v.to_owned())
+}
+
+fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
+ get_browser_ui_test_version_inner(npm, false)
+ .or_else(|| get_browser_ui_test_version_inner(npm, true))
+}
+
+fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
+ match fs::read_to_string(
+ src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
+ ) {
+ Ok(v) => {
+ if v.trim() != installed_version {
+ eprintln!(
+ "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
+ one used in the CI (`{}`)",
+ installed_version, v
+ );
+ eprintln!(
+ "You can install this version using `npm update browser-ui-test` or by using \
+ `npm install browser-ui-test@{}`",
+ v,
+ );
+ }
+ }
+ Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
+ }
+}
+
+fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
+ for entry in walkdir::WalkDir::new(path) {
+ let entry = entry.ok()?;
+ if entry.file_type().is_file() && entry.file_name() == "lib.rs" {
+ return Some(entry.path().to_path_buf());
+ }
+ }
+ None
+}
+
+// FIXME: move `bootstrap::util::try_run` into `build_helper` crate
+// and use that one instead of creating this function.
+fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+ let status = match cmd.status() {
+ Ok(status) => status,
+ Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cmd, e),
+ };
+ if !status.success() && print_cmd_on_fail {
+ println!(
+ "\n\ncommand did not execute successfully: {:?}\n\
+ expected success, got: {}\n\n",
+ cmd, status
+ );
+ }
+ status.success()
+}
+
+fn main() {
+ let config = Arc::new(Config::from_args(env::args().collect()));
+
+ // The goal here is to check if the necessary packages are installed, and if not, we
+ // panic.
+ match get_browser_ui_test_version(&config.npm) {
+ Some(version) => {
+ // We also check the version currently used in CI and emit a warning if it's not the
+ // same one.
+ compare_browser_ui_test_version(&version, &config.rust_src);
+ }
+ None => {
+ eprintln!(
+ r#"
+error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` dependency is missing.
+
+If you want to install the `browser-ui-test` dependency, run `npm install browser-ui-test`
+"#,
+ );
+
+ panic!("Cannot run rustdoc-gui tests");
+ }
+ }
+
+ let src_path = config.rust_src.join("tests/rustdoc-gui/src");
+ for entry in src_path.read_dir().expect("read_dir call failed") {
+ if let Ok(entry) = entry {
+ let path = entry.path();
+
+ if !path.is_dir() {
+ continue;
+ }
+
+ let mut cargo = Command::new(&config.initial_cargo);
+ cargo
+ .arg("doc")
+ .arg("--target-dir")
+ .arg(&config.out_dir)
+ .env("RUSTC_BOOTSTRAP", "1")
+ .env("RUSTDOC", &config.rustdoc)
+ .env("RUSTC", &config.rustc)
+ .current_dir(path);
+
+ if let Some(librs) = find_librs(entry.path()) {
+ let compiletest_c = compiletest::common::Config {
+ edition: None,
+ mode: compiletest::common::Mode::Rustdoc,
+ ..Default::default()
+ };
+
+ let test_props = TestProps::from_file(&librs, None, &compiletest_c);
+
+ if !test_props.compile_flags.is_empty() {
+ cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
+ }
+
+ if let Some(flags) = &test_props.run_flags {
+ cargo.arg(flags);
+ }
+ }
+
+ try_run(&mut cargo, config.verbose);
+ }
+ }
+
+ let mut command = Command::new(&config.nodejs);
+ command
+ .arg(config.rust_src.join("src/tools/rustdoc-gui/tester.js"))
+ .arg("--jobs")
+ .arg(&config.jobs)
+ .arg("--doc-folder")
+ .arg(config.out_dir.join("doc"))
+ .arg("--tests-folder")
+ .arg(config.rust_src.join("tests/rustdoc-gui"));
+
+ for file in &config.goml_files {
+ command.arg("--file").arg(file);
+ }
+
+ command.args(&config.test_args);
+
+ try_run(&mut command, config.verbose);
+}
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
new file mode 100644
index 0000000..5f8eaeb
--- /dev/null
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -0,0 +1,72 @@
+//! Checks that all Flunt files have messages in alphabetical order
+
+use crate::walk::{filter_dirs, walk};
+use std::{fs::OpenOptions, io::Write, path::Path};
+
+use regex::Regex;
+
+lazy_static::lazy_static! {
+ static ref MESSAGE: Regex = Regex::new(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#).unwrap();
+}
+
+fn filter_fluent(path: &Path) -> bool {
+ if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
+}
+
+fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+ let mut matches = MESSAGE.captures_iter(fluent).peekable();
+ while let Some(m) = matches.next() {
+ if let Some(next) = matches.peek() {
+ let name = m.get(1).unwrap();
+ let next = next.get(1).unwrap();
+ if name.as_str() > next.as_str() {
+ tidy_error!(
+ bad,
+ "{filename}: message `{}` appears before `{}`, but is alphabetically later than it
+run tidy with `--bless` to sort the file correctly",
+ name.as_str(),
+ next.as_str()
+ );
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+fn sort_messages(fluent: &str) -> String {
+ let mut chunks = vec![];
+ let mut cur = String::new();
+ for line in fluent.lines() {
+ if MESSAGE.is_match(line) {
+ chunks.push(std::mem::take(&mut cur));
+ }
+ cur += line;
+ cur.push('\n');
+ }
+ chunks.push(cur);
+ chunks.sort();
+ let mut out = chunks.join("");
+ out = out.trim().to_string();
+ out.push('\n');
+ out
+}
+
+pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+ walk(
+ path,
+ |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
+ &mut |ent, contents| {
+ if bless {
+ let sorted = sort_messages(contents);
+ if sorted != contents {
+ let mut f =
+ OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
+ f.write(sorted.as_bytes()).unwrap();
+ }
+ } else {
+ check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+ }
+ },
+ );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 3500032..e467514 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -59,6 +59,7 @@
pub mod error_codes;
pub mod extdeps;
pub mod features;
+pub mod fluent_alphabetical;
pub mod mir_opt_tests;
pub mod pal;
pub mod primitive_docs;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index f59406c..1c4d96c 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -96,6 +96,7 @@
// Checks that only make sense for the compiler.
check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
+ check!(fluent_alphabetical, &compiler_path, bless);
// Checks that only make sense for the std libs.
check!(pal, &library_path);
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
index c3ffaeb..f88d695 100644
--- a/tests/codegen/alloc-optimisation.rs
+++ b/tests/codegen/alloc-optimisation.rs
@@ -1,12 +1,13 @@
//
// no-system-llvm
// compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
#[no_mangle]
pub fn alloc_test(data: u32) {
// CHECK-LABEL: @alloc_test
// CHECK-NEXT: start:
+ // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
// CHECK-NEXT: ret void
let x = Box::new(data);
drop(x);
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index d82b737..e52392b 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -11,8 +11,6 @@
// Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
// This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.0 = private constant <{
-// CHECK: @vtable.1 = private constant <{
// CHECK: @vtable.2 = private constant <{
// CHECK: @vtable.3 = private constant <{
// CHECK: @vtable.4 = private constant <{
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
index 9143fad..6f477a7 100644
--- a/tests/codegen/vec-optimizes-away.rs
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -1,12 +1,13 @@
// ignore-debug: the debug assertions get in the way
// no-system-llvm
// compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
#[no_mangle]
pub fn sum_me() -> i32 {
// CHECK-LABEL: @sum_me
// CHECK-NEXT: {{^.*:$}}
+ // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
// CHECK-NEXT: ret i32 6
vec![1, 2, 3].iter().sum::<i32>()
}
diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
index d342b2f..b59a65a 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -18,7 +18,7 @@
extern crate rustc_middle;
extern crate rustc_session;
-use rustc_borrowck::consumers::BodyWithBorrowckFacts;
+use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions};
use rustc_driver::Compilation;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -102,7 +102,7 @@
println!("Bodies retrieved for:");
for (def_id, body) in bodies {
println!("{}", def_id);
- assert!(body.input_facts.cfg_edge.len() > 0);
+ assert!(body.input_facts.unwrap().cfg_edge.len() > 0);
}
});
@@ -127,7 +127,8 @@
}
fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> {
- let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id);
+ let opts = ConsumerOptions::PoloniusInputFacts;
+ let body_with_facts = consumers::get_body_with_borrowck_facts(tcx, def_id, opts);
// SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
let body_with_facts: BodyWithBorrowckFacts<'static> =
unsafe { std::mem::transmute(body_with_facts) };
diff --git a/tests/run-make/no-alloc-shim/Makefile b/tests/run-make/no-alloc-shim/Makefile
new file mode 100644
index 0000000..568e3f9
--- /dev/null
+++ b/tests/run-make/no-alloc-shim/Makefile
@@ -0,0 +1,24 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain
+
+TARGET_LIBDIR = $$($(RUSTC) --print target-libdir)
+
+all:
+ $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort
+ifdef IS_MSVC
+ $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib
+ $(call OUT_EXE,foo)
+else
+ $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo)
+ $(call RUN_BINFILE,foo)
+endif
+
+ # Check that linking without __rust_no_alloc_shim_is_unstable defined fails
+ $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort --cfg check_feature_gate
+ifdef IS_MSVC
+ $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib || exit 0 && exit 1
+else
+ $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) || exit 0 && exit 1
+endif
diff --git a/tests/run-make/no-alloc-shim/foo.rs b/tests/run-make/no-alloc-shim/foo.rs
new file mode 100644
index 0000000..a3daec3
--- /dev/null
+++ b/tests/run-make/no-alloc-shim/foo.rs
@@ -0,0 +1,44 @@
+#![feature(default_alloc_error_handler)]
+#![no_std]
+#![no_main]
+
+extern crate alloc;
+
+use alloc::alloc::{GlobalAlloc, Layout};
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[no_mangle]
+extern "C" fn rust_eh_personality() {
+ loop {}
+}
+
+#[global_allocator]
+static ALLOC: Alloc = Alloc;
+
+struct Alloc;
+
+unsafe impl GlobalAlloc for Alloc {
+ unsafe fn alloc(&self, _: Layout) -> *mut u8 {
+ core::ptr::null_mut()
+ }
+ unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
+ todo!()
+ }
+}
+
+#[cfg(not(check_feature_gate))]
+#[no_mangle]
+static __rust_no_alloc_shim_is_unstable: u8 = 0;
+
+#[no_mangle]
+extern "C" fn main(_argc: usize, _argv: *const *const i8) -> i32 {
+ unsafe {
+ assert_eq!(alloc::alloc::alloc(Layout::new::<()>()), core::ptr::null_mut());
+ }
+
+ 0
+}
diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml
index 3d88d56..67f1497 100644
--- a/tests/rustdoc-gui/source-anchor-scroll.goml
+++ b/tests/rustdoc-gui/source-anchor-scroll.goml
@@ -8,13 +8,13 @@
assert-property: ("html", {"scrollTop": "0"})
click: '//a[text() = "barbar"]'
-assert-property: ("html", {"scrollTop": "125"})
+assert-property: ("html", {"scrollTop": "149"})
click: '//a[text() = "bar"]'
-assert-property: ("html", {"scrollTop": "156"})
+assert-property: ("html", {"scrollTop": "180"})
click: '//a[text() = "sub_fn"]'
-assert-property: ("html", {"scrollTop": "53"})
+assert-property: ("html", {"scrollTop": "77"})
// We now check that clicking on lines doesn't change the scroll
// Extra information: the "sub_fn" function header is on line 1.
click: '//*[@id="6"]'
-assert-property: ("html", {"scrollTop": "53"})
+assert-property: ("html", {"scrollTop": "77"})
diff --git a/tests/rustdoc-gui/src/extend_css/lib.rs b/tests/rustdoc-gui/src/extend_css/lib.rs
index 3a3babf..2308c09 100644
--- a/tests/rustdoc-gui/src/extend_css/lib.rs
+++ b/tests/rustdoc-gui/src/extend_css/lib.rs
@@ -1 +1,2 @@
+// compile-flags: --extend-css extra.css
//! <div class="extend">text in red</div>
diff --git a/tests/rustdoc-gui/src/link_to_definition/lib.rs b/tests/rustdoc-gui/src/link_to_definition/lib.rs
index 419a9cc..6fed79a 100644
--- a/tests/rustdoc-gui/src/link_to_definition/lib.rs
+++ b/tests/rustdoc-gui/src/link_to_definition/lib.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
pub fn sub_fn() {
barbar();
}
diff --git a/tests/rustdoc-gui/src/scrape_examples/src/lib.rs b/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
index 88b03cf..6666587 100644
--- a/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
+++ b/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
@@ -1,3 +1,4 @@
+// run-flags:-Zrustdoc-scrape-examples
/// # Examples
///
/// ```
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index f1ad7c8..e99cd1f 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -340,3 +340,15 @@
/// level changes.
pub mod tracing_macro {}
}
+
+/// Regression test for <https://github.com/rust-lang/rust/issues/111117>
+pub mod trillium_server_common {
+ /// One-indexed, because the first CloneCounter is included. If you don't
+ /// want the original to count, construct a [``CloneCounterObserver`]
+ /// instead and use [`CloneCounterObserver::counter`] to increment.
+ //~^ ERROR unescaped backtick
+ pub struct CloneCounter;
+
+ /// This is used by the above.
+ pub struct CloneCounterObserver;
+}
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index e629dbc..bf1f188 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -342,6 +342,18 @@
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
error: unescaped backtick
+ --> $DIR/unescaped_backticks.rs:348:56
+ |
+LL | /// instead and use [`CloneCounterObserver::counter`] to increment.
+ | ^
+ |
+ = help: the opening or closing backtick of an inline code may be missing
+help: if you meant to use a literal backtick, escape it
+ |
+LL | /// instead and use [`CloneCounterObserver::counter\`] to increment.
+ | +
+
+error: unescaped backtick
--> $DIR/unescaped_backticks.rs:11:5
|
LL | /// `
@@ -955,5 +967,5 @@
LL | /// | table`( | )\`body |
| +
-error: aborting due to 63 previous errors
+error: aborting due to 64 previous errors
diff --git a/tests/rustdoc/strikethrough-in-summary.rs b/tests/rustdoc/strikethrough-in-summary.rs
deleted file mode 100644
index cb6cd0e..0000000
--- a/tests/rustdoc/strikethrough-in-summary.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![crate_name = "foo"]
-
-// @has foo/index.html '//del' 'strike'
-
-/// ~~strike~~
-pub fn strike() {}
diff --git a/tests/rustdoc/test-strikethrough.rs b/tests/rustdoc/test-strikethrough.rs
index c785572..5816215 100644
--- a/tests/rustdoc/test-strikethrough.rs
+++ b/tests/rustdoc/test-strikethrough.rs
@@ -1,6 +1,13 @@
#![crate_name = "foo"]
-// @has foo/fn.f.html
-// @has - //del "Y"
-/// ~~Y~~
+// Test that strikethrough works with single and double tildes and that it shows up on
+// the item's dedicated page as well as the parent module's summary of items.
+
+// @has foo/index.html //del 'strike'
+// @has foo/index.html //del 'through'
+
+// @has foo/fn.f.html //del 'strike'
+// @has foo/fn.f.html //del 'through'
+
+/// ~~strike~~ ~through~
pub fn f() {}
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
index 127a3f5..1bda7a4 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -8,7 +8,6 @@
//~^ NOTE `vec[_]` is borrowed here
vec[0] = Box::new(4); //~ ERROR cannot assign
//~^ NOTE `vec[_]` is assigned to here
- //~| NOTE in this expansion of desugaring of drop and replace
_a.use_ref();
//~^ NOTE borrow later used here
}
@@ -23,7 +22,6 @@
//~^ `vec[_]` is borrowed here
vec[0] = Box::new(4); //~ ERROR cannot assign
//~^ NOTE `vec[_]` is assigned to here
- //~| NOTE in this expansion of desugaring of drop and replace
_b.use_ref();
//~^ NOTE borrow later used here
}
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index 5e1251b..70b9e4f 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -6,24 +6,24 @@
LL |
LL | vec[0] = Box::new(4);
| ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-...
+LL |
LL | _a.use_ref();
| ------------ borrow later used here
error[E0506]: cannot assign to `vec[_]` because it is borrowed
- --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
|
LL | &mut [ref _b @ ..] => {
| ------ `vec[_]` is borrowed here
LL |
LL | vec[0] = Box::new(4);
| ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-...
+LL |
LL | _b.use_ref();
| ------------ borrow later used here
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:36:11
+ --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
|
LL | match vec {
| ^^^ cannot move out of here
@@ -41,7 +41,7 @@
|
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:48:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
|
LL | let a = vec[0];
| ^^^^^^
@@ -55,7 +55,7 @@
| +
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:57:11
+ --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
|
LL | match vec {
| ^^^ cannot move out of here
@@ -73,7 +73,7 @@
|
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:67:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
|
LL | let a = vec[0];
| ^^^^^^
@@ -87,7 +87,7 @@
| +
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:76:11
+ --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
|
LL | match vec {
| ^^^ cannot move out of here
@@ -106,7 +106,7 @@
|
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:87:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
|
LL | let a = vec[0];
| ^^^^^^
diff --git a/tests/ui/borrowck/issue-45199.rs b/tests/ui/borrowck/issue-45199.rs
index 6a6b255..ded46e5 100644
--- a/tests/ui/borrowck/issue-45199.rs
+++ b/tests/ui/borrowck/issue-45199.rs
@@ -5,7 +5,6 @@
b = Box::new(1); //~ NOTE first assignment
b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
//~| NOTE cannot assign twice to immutable
- //~| NOTE in this expansion of desugaring of drop and replace
}
fn test_call() {
@@ -14,14 +13,12 @@
//~| SUGGESTION mut b
b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
//~| NOTE cannot assign twice to immutable
- //~| NOTE in this expansion of desugaring of drop and replace
}
fn test_args(b: Box<i32>) { //~ HELP consider making this binding mutable
//~| SUGGESTION mut b
b = Box::new(2); //~ ERROR cannot assign to immutable argument `b`
//~| NOTE cannot assign to immutable argument
- //~| NOTE in this expansion of desugaring of drop and replace
}
fn main() {}
diff --git a/tests/ui/borrowck/issue-45199.stderr b/tests/ui/borrowck/issue-45199.stderr
index 163f237..47aa309 100644
--- a/tests/ui/borrowck/issue-45199.stderr
+++ b/tests/ui/borrowck/issue-45199.stderr
@@ -10,7 +10,7 @@
| ^ cannot assign twice to immutable variable
error[E0384]: cannot assign twice to immutable variable `b`
- --> $DIR/issue-45199.rs:15:5
+ --> $DIR/issue-45199.rs:14:5
|
LL | let b = Box::new(1);
| -
@@ -22,7 +22,7 @@
| ^ cannot assign twice to immutable variable
error[E0384]: cannot assign to immutable argument `b`
- --> $DIR/issue-45199.rs:22:5
+ --> $DIR/issue-45199.rs:20:5
|
LL | fn test_args(b: Box<i32>) {
| - help: consider making this binding mutable: `mut b`
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
index 56f5ac4..41b09ba 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
@@ -1,6 +1,7 @@
// edition:2021
#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
// Should capture the discriminant since a variant of a multivariant enum is
// mentioned in the match arm; the discriminant is captured by the closure regardless
@@ -8,9 +9,6 @@
fn test_1_should_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@@ -29,8 +27,6 @@
fn test_2_should_not_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match variant {
@@ -50,8 +46,6 @@
fn test_3_should_not_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match variant {
@@ -66,8 +60,6 @@
fn test_6_should_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@@ -88,8 +80,6 @@
fn test_4_should_not_capture_array() {
let array: [i32; 3] = [0; 3];
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match array {
@@ -112,8 +102,6 @@
fn test_5_should_capture_multi_variant() {
let variant = MVariant::A;
let c = #[rustc_capture_analysis]
- //~^ ERROR: attributes on expressions are experimental
- //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@@ -127,6 +115,62 @@
c();
}
+// Even though all patterns are wild, we need to read the discriminant
+// in order to test the slice length
+fn test_7_should_capture_slice_len() {
+ let slice: &[i32] = &[1, 2, 3];
+ let c = #[rustc_capture_analysis]
+ || {
+ //~^ First Pass analysis includes:
+ //~| Min Capture analysis includes:
+ match slice {
+ //~^ NOTE: Capturing slice[] -> ImmBorrow
+ //~| NOTE: Min Capture slice[] -> ImmBorrow
+ [_,_,_] => {},
+ _ => {}
+ }
+ };
+ c();
+ let c = #[rustc_capture_analysis]
+ || {
+ //~^ First Pass analysis includes:
+ //~| Min Capture analysis includes:
+ match slice {
+ //~^ NOTE: Capturing slice[] -> ImmBorrow
+ //~| NOTE: Min Capture slice[] -> ImmBorrow
+ [] => {},
+ _ => {}
+ }
+ };
+ c();
+ let c = #[rustc_capture_analysis]
+ || {
+ //~^ First Pass analysis includes:
+ //~| Min Capture analysis includes:
+ match slice {
+ //~^ NOTE: Capturing slice[] -> ImmBorrow
+ //~| NOTE: Min Capture slice[] -> ImmBorrow
+ [_, .. ,_] => {},
+ _ => {}
+ }
+ };
+ c();
+}
+
+// Wild pattern that doesn't bind, so no capture
+fn test_8_capture_slice_wild() {
+ let slice: &[i32] = &[1, 2, 3];
+ let c = #[rustc_capture_analysis]
+ || {
+ //~^ First Pass analysis includes:
+ match slice {
+ [..] => {},
+ _ => {}
+ }
+ };
+ c();
+}
+
fn main() {
test_1_should_capture();
test_2_should_not_capture();
@@ -134,4 +178,6 @@
test_6_should_capture_single_variant();
test_4_should_not_capture_array();
test_5_should_capture_multi_variant();
+ test_7_should_capture_slice_len();
+ test_8_capture_slice_wild();
}
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
index 4608133..e137af1 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
@@ -1,59 +1,5 @@
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:10:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:31:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:52:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:68:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:90:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
- --> $DIR/patterns-capture-analysis.rs:114:14
- |
-LL | let c = #[rustc_capture_analysis]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
- = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:14:5
+ --> $DIR/patterns-capture-analysis.rs:12:5
|
LL | / || {
LL | |
@@ -65,13 +11,13 @@
| |_____^
|
note: Capturing variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:17:15
+ --> $DIR/patterns-capture-analysis.rs:15:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
- --> $DIR/patterns-capture-analysis.rs:14:5
+ --> $DIR/patterns-capture-analysis.rs:12:5
|
LL | / || {
LL | |
@@ -83,13 +29,13 @@
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:17:15
+ --> $DIR/patterns-capture-analysis.rs:15:15
|
LL | match variant {
| ^^^^^^^
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:34:5
+ --> $DIR/patterns-capture-analysis.rs:30:5
|
LL | / || {
LL | |
@@ -100,7 +46,7 @@
| |_____^
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:55:5
+ --> $DIR/patterns-capture-analysis.rs:49:5
|
LL | / || {
LL | |
@@ -111,7 +57,7 @@
| |_____^
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:71:5
+ --> $DIR/patterns-capture-analysis.rs:63:5
|
LL | / || {
LL | |
@@ -123,18 +69,18 @@
| |_____^
|
note: Capturing variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:74:15
+ --> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
note: Capturing variant[(0, 0)] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:74:15
+ --> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
- --> $DIR/patterns-capture-analysis.rs:71:5
+ --> $DIR/patterns-capture-analysis.rs:63:5
|
LL | / || {
LL | |
@@ -146,13 +92,13 @@
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:74:15
+ --> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:93:5
+ --> $DIR/patterns-capture-analysis.rs:83:5
|
LL | / || {
LL | |
@@ -163,7 +109,7 @@
| |_____^
error: First Pass analysis includes:
- --> $DIR/patterns-capture-analysis.rs:117:5
+ --> $DIR/patterns-capture-analysis.rs:105:5
|
LL | / || {
LL | |
@@ -175,13 +121,13 @@
| |_____^
|
note: Capturing variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:120:15
+ --> $DIR/patterns-capture-analysis.rs:108:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
- --> $DIR/patterns-capture-analysis.rs:117:5
+ --> $DIR/patterns-capture-analysis.rs:105:5
|
LL | / || {
LL | |
@@ -193,11 +139,130 @@
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
- --> $DIR/patterns-capture-analysis.rs:120:15
+ --> $DIR/patterns-capture-analysis.rs:108:15
|
LL | match variant {
| ^^^^^^^
-error: aborting due to 15 previous errors
+error: First Pass analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:123:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Capturing slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:126:15
+ |
+LL | match slice {
+ | ^^^^^
-For more information about this error, try `rustc --explain E0658`.
+error: Min Capture analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:123:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Min Capture slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:126:15
+ |
+LL | match slice {
+ | ^^^^^
+
+error: First Pass analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:135:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Capturing slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:138:15
+ |
+LL | match slice {
+ | ^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:135:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Min Capture slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:138:15
+ |
+LL | match slice {
+ | ^^^^^
+
+error: First Pass analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:147:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Capturing slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:150:15
+ |
+LL | match slice {
+ | ^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:147:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | match slice {
+... |
+LL | | }
+LL | | };
+ | |_____^
+ |
+note: Min Capture slice[] -> ImmBorrow
+ --> $DIR/patterns-capture-analysis.rs:150:15
+ |
+LL | match slice {
+ | ^^^^^
+
+error: First Pass analysis includes:
+ --> $DIR/patterns-capture-analysis.rs:164:5
+ |
+LL | / || {
+LL | |
+LL | | match slice {
+LL | | [..] => {},
+LL | | _ => {}
+LL | | }
+LL | | };
+ | |_____^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
index 85345d6..b22cab7 100644
--- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
@@ -1,7 +1,7 @@
-// check-pass
+// known-bug: #110395
// known-bug: #97156
-#![feature(const_type_id, generic_const_exprs)]
+#![feature(const_type_id, const_trait_impl, generic_const_exprs)]
#![allow(incomplete_features)]
use std::any::TypeId;
@@ -26,7 +26,10 @@
trait WithAssoc<U> {
type Assoc;
}
-impl<T: 'static> WithAssoc<()> for T where [(); <T as AssocCt>::ASSOC]: {
+impl<T: 'static> WithAssoc<()> for T
+where
+ [(); <T as AssocCt>::ASSOC]:,
+{
type Assoc = [u8; <T as AssocCt>::ASSOC];
}
@@ -38,7 +41,6 @@
x
}
-
fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc
where
One: WithAssoc<T>,
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
new file mode 100644
index 0000000..8cbd126
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `TypeId` in a pattern, `TypeId` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/typeid-equality-by-subtyping.rs:18:9
+ |
+LL | WHAT_A_TYPE => 0,
+ | ^^^^^^^^^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to previous error
+
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 41b0981..3d1197a 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -4,8 +4,8 @@
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
- = note: source type: `[[u32; H+1]; W]` (generic size [const expr])
- = note: target type: `[[u32; W+1]; H]` (generic size [const expr])
+ = note: source type: `[[u32; H+1]; W]` (generic size {const expr})
+ = note: target type: `[[u32; W+1]; H]` (generic size {const expr})
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:16:5
@@ -34,8 +34,8 @@
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
- = note: source type: `[[u32; H]; W]` (generic size [const expr])
- = note: target type: `[u32; W * H * H]` (generic size [const expr])
+ = note: source type: `[[u32; H]; W]` (generic size {const expr})
+ = note: target type: `[u32; W * H * H]` (generic size {const expr})
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:30:5
diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr
index 319d2b9..dc2c702 100644
--- a/tests/ui/consts/const_cmp_type_id.stderr
+++ b/tests/ui/consts/const_cmp_type_id.stderr
@@ -20,7 +20,6 @@
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: can't compare `TypeId` with `TypeId` in const contexts
--> $DIR/const_cmp_type_id.rs:9:13
@@ -44,7 +43,6 @@
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: can't compare `TypeId` with `TypeId` in const contexts
--> $DIR/const_cmp_type_id.rs:10:22
diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr
index 95ab78b..09661d3 100644
--- a/tests/ui/consts/issue-73976-monomorphic.stderr
+++ b/tests/ui/consts/issue-73976-monomorphic.stderr
@@ -20,7 +20,6 @@
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
diff --git a/tests/ui/dyn-star/param-env-infer.current.stderr b/tests/ui/dyn-star/param-env-infer.current.stderr
index d0785c8..b3af7be 100644
--- a/tests/ui/dyn-star/param-env-infer.current.stderr
+++ b/tests/ui/dyn-star/param-env-infer.current.stderr
@@ -8,7 +8,7 @@
= note: `#[warn(incomplete_features)]` on by default
error[E0282]: type annotations needed
- --> $DIR/param-env-infer.rs:12:10
+ --> $DIR/param-env-infer.rs:13:10
|
LL | t as _
| ^ cannot infer type
diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr
index d0785c8..64d76bb 100644
--- a/tests/ui/dyn-star/param-env-infer.next.stderr
+++ b/tests/ui/dyn-star/param-env-infer.next.stderr
@@ -7,12 +7,67 @@
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
-error[E0282]: type annotations needed
- --> $DIR/param-env-infer.rs:12:10
+error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
+ --> $DIR/param-env-infer.rs:11:60
|
-LL | t as _
- | ^ cannot infer type
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...which requires borrow-checking `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires preparing `make_dyn_star` for borrow checking...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building THIR for `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `make_dyn_star`...
+ --> $DIR/param-env-infer.rs:11:1
+ |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing layout of `make_dyn_star::{opaque#0}`...
+ = note: ...which requires normalizing `make_dyn_star::{opaque#0}`...
+ = note: ...which again requires computing type of `make_dyn_star::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+ --> $DIR/param-env-infer.rs:5:1
+ |
+LL | / #![feature(dyn_star, pointer_like_trait)]
+LL | |
+LL | |
+LL | | use std::fmt::Debug;
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error: aborting due to previous error; 1 warning emitted
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/dyn-star/param-env-infer.rs b/tests/ui/dyn-star/param-env-infer.rs
index 9039dde..1fb16d7 100644
--- a/tests/ui/dyn-star/param-env-infer.rs
+++ b/tests/ui/dyn-star/param-env-infer.rs
@@ -9,8 +9,9 @@
use std::marker::PointerLike;
fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+ //[next]~^ ERROR cycle detected when computing type of `make_dyn_star::{opaque#0}`
t as _
- //~^ ERROR type annotations needed
+ //[current]~^ ERROR type annotations needed
}
fn main() {}
diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.rs b/tests/ui/editions/edition-raw-pointer-method-2018.rs
index af0b2d6..0bae65a 100644
--- a/tests/ui/editions/edition-raw-pointer-method-2018.rs
+++ b/tests/ui/editions/edition-raw-pointer-method-2018.rs
@@ -7,5 +7,5 @@
let x = 0;
let y = &x as *const _;
let _ = y.is_null();
- //~^ error: the type of this value must be known to call a method on a raw pointer on it [E0699]
+ //~^ error: cannot call a method on a raw pointer with an unknown pointee type [E0699]
}
diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.stderr b/tests/ui/editions/edition-raw-pointer-method-2018.stderr
index 2345249..b9afa01 100644
--- a/tests/ui/editions/edition-raw-pointer-method-2018.stderr
+++ b/tests/ui/editions/edition-raw-pointer-method-2018.stderr
@@ -1,4 +1,4 @@
-error[E0699]: the type of this value must be known to call a method on a raw pointer on it
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
--> $DIR/edition-raw-pointer-method-2018.rs:9:15
|
LL | let _ = y.is_null();
diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs b/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
new file mode 100644
index 0000000..8ef9281
--- /dev/null
+++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
@@ -0,0 +1,22 @@
+struct Header;
+struct EntryMetadata;
+struct Entry<A, B>(A, B);
+
+trait Tr {
+ type EncodedKey;
+ type EncodedValue;
+}
+
+fn test<C: Tr, R>(
+ // This APIT is long, however we shouldn't render the type name with a newline in it.
+ y: impl FnOnce(
+ &mut Header,
+ &mut [EntryMetadata],
+ &mut [Entry<C::EncodedKey, C::EncodedValue>]
+ ) -> R,
+) {
+ let () = y;
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
new file mode 100644
index 0000000..40446a3
--- /dev/null
+++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+ --> $DIR/arg-position-impl-trait-too-long.rs:18:9
+ |
+LL | y: impl FnOnce(
+ | ________-
+LL | | &mut Header,
+LL | | &mut [EntryMetadata],
+LL | | &mut [Entry<C::EncodedKey, C::EncodedValue>]
+LL | | ) -> R,
+ | |__________- this type parameter
+LL | ) {
+LL | let () = y;
+ | ^^ - this expression has type `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
+ | |
+ | expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`, found `()`
+ |
+ = note: expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
+ found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.rs b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
new file mode 100644
index 0000000..c3a6f09
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
@@ -0,0 +1,12 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<T: Trait, U: Trait>() -> impl Trait {
+ //~^ WARN function cannot return without recursing [unconditional_recursion]
+ let a: T = foo::<T, U>();
+ //~^ ERROR concrete type differs from previous defining opaque type use
+ loop {}
+ let _: T = foo::<U, T>();
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
new file mode 100644
index 0000000..0699174
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
@@ -0,0 +1,26 @@
+warning: function cannot return without recursing
+ --> $DIR/multiple-defining-usages-in-body.rs:4:1
+ |
+LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL | let a: T = foo::<T, U>();
+ | ------------- recursive call site
+ |
+ = help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
+
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/multiple-defining-usages-in-body.rs:6:16
+ |
+LL | let a: T = foo::<T, U>();
+ | ^^^^^^^^^^^^^ expected `U`, got `T`
+ |
+note: previous use here
+ --> $DIR/multiple-defining-usages-in-body.rs:9:16
+ |
+LL | let _: T = foo::<U, T>();
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/lint/lint-attr-everywhere-early.rs b/tests/ui/lint/lint-attr-everywhere-early.rs
index fd0c4b4..0c820ef 100644
--- a/tests/ui/lint/lint-attr-everywhere-early.rs
+++ b/tests/ui/lint/lint-attr-everywhere-early.rs
@@ -134,6 +134,14 @@
}
}
+ match f {
+ #[deny(ellipsis_inclusive_range_patterns)]
+ Match{f1: 0...100} => {}
+ //~^ ERROR range patterns are deprecated
+ //~| WARNING this is accepted in the current edition
+ _ => {}
+ }
+
// Statement Block
{
#![deny(unsafe_code)]
diff --git a/tests/ui/lint/lint-attr-everywhere-early.stderr b/tests/ui/lint/lint-attr-everywhere-early.stderr
index d6c6d5f..fac0eb4 100644
--- a/tests/ui/lint/lint-attr-everywhere-early.stderr
+++ b/tests/ui/lint/lint-attr-everywhere-early.stderr
@@ -384,92 +384,106 @@
LL | #[deny(while_true)]
| ^^^^^^^^^^
+error: `...` range patterns are deprecated
+ --> $DIR/lint-attr-everywhere-early.rs:139:20
+ |
+LL | Match{f1: 0...100} => {}
+ | ^^^ help: use `..=` for an inclusive range
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-early.rs:138:16
+ |
+LL | #[deny(ellipsis_inclusive_range_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:140:9
+ --> $DIR/lint-attr-everywhere-early.rs:148:9
|
LL | unsafe {}
| ^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:139:17
+ --> $DIR/lint-attr-everywhere-early.rs:147:17
|
LL | #![deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:144:9
+ --> $DIR/lint-attr-everywhere-early.rs:152:9
|
LL | unsafe {}
| ^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:143:16
+ --> $DIR/lint-attr-everywhere-early.rs:151:16
|
LL | #[deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:149:5
+ --> $DIR/lint-attr-everywhere-early.rs:157:5
|
LL | unsafe {};
| ^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:148:12
+ --> $DIR/lint-attr-everywhere-early.rs:156:12
|
LL | #[deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:151:27
+ --> $DIR/lint-attr-everywhere-early.rs:159:27
|
LL | [#[deny(unsafe_code)] unsafe {123}];
| ^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:151:13
+ --> $DIR/lint-attr-everywhere-early.rs:159:13
|
LL | [#[deny(unsafe_code)] unsafe {123}];
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:152:27
+ --> $DIR/lint-attr-everywhere-early.rs:160:27
|
LL | (#[deny(unsafe_code)] unsafe {123},);
| ^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:152:13
+ --> $DIR/lint-attr-everywhere-early.rs:160:13
|
LL | (#[deny(unsafe_code)] unsafe {123},);
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:154:31
+ --> $DIR/lint-attr-everywhere-early.rs:162:31
|
LL | call(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:154:17
+ --> $DIR/lint-attr-everywhere-early.rs:162:17
|
LL | call(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^
error: usage of an `unsafe` block
- --> $DIR/lint-attr-everywhere-early.rs:156:38
+ --> $DIR/lint-attr-everywhere-early.rs:164:38
|
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:156:24
+ --> $DIR/lint-attr-everywhere-early.rs:164:24
|
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^
error: `...` range patterns are deprecated
- --> $DIR/lint-attr-everywhere-early.rs:167:18
+ --> $DIR/lint-attr-everywhere-early.rs:175:18
|
LL | f1: 0...100,
| ^^^ help: use `..=` for an inclusive range
@@ -477,10 +491,10 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-early.rs:166:20
+ --> $DIR/lint-attr-everywhere-early.rs:174:20
|
LL | #[deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 36 previous errors
+error: aborting due to 37 previous errors
diff --git a/tests/ui/lint/lint-attr-everywhere-late.rs b/tests/ui/lint/lint-attr-everywhere-late.rs
index 1055157..a24355b 100644
--- a/tests/ui/lint/lint-attr-everywhere-late.rs
+++ b/tests/ui/lint/lint-attr-everywhere-late.rs
@@ -162,6 +162,11 @@
}
}
+ match 123 {
+ #[deny(non_snake_case)]
+ ARM_VAR => {} //~ ERROR variable `ARM_VAR` should have a snake case name
+ }
+
// Statement Block
{
#![deny(enum_intrinsics_non_enums)]
diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr
index a69c2e0..9587556 100644
--- a/tests/ui/lint/lint-attr-everywhere-late.stderr
+++ b/tests/ui/lint/lint-attr-everywhere-late.stderr
@@ -305,124 +305,136 @@
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+error: variable `ARM_VAR` should have a snake case name
+ --> $DIR/lint-attr-everywhere-late.rs:167:9
+ |
+LL | ARM_VAR => {}
+ | ^^^^^^^ help: convert the identifier to snake case: `arm_var`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:166:16
+ |
+LL | #[deny(non_snake_case)]
+ | ^^^^^^^^^^^^^^
+
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:168:9
+ --> $DIR/lint-attr-everywhere-late.rs:173:9
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:168:29
+ --> $DIR/lint-attr-everywhere-late.rs:173:29
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:167:17
+ --> $DIR/lint-attr-everywhere-late.rs:172:17
|
LL | #![deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:172:9
+ --> $DIR/lint-attr-everywhere-late.rs:177:9
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:172:29
+ --> $DIR/lint-attr-everywhere-late.rs:177:29
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:171:16
+ --> $DIR/lint-attr-everywhere-late.rs:176:16
|
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:177:5
+ --> $DIR/lint-attr-everywhere-late.rs:182:5
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:177:25
+ --> $DIR/lint-attr-everywhere-late.rs:182:25
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:176:12
+ --> $DIR/lint-attr-everywhere-late.rs:181:12
|
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:179:41
+ --> $DIR/lint-attr-everywhere-late.rs:184:41
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:179:61
+ --> $DIR/lint-attr-everywhere-late.rs:184:61
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:179:13
+ --> $DIR/lint-attr-everywhere-late.rs:184:13
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:180:41
+ --> $DIR/lint-attr-everywhere-late.rs:185:41
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:180:61
+ --> $DIR/lint-attr-everywhere-late.rs:185:61
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:180:13
+ --> $DIR/lint-attr-everywhere-late.rs:185:13
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:182:45
+ --> $DIR/lint-attr-everywhere-late.rs:187:45
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:182:65
+ --> $DIR/lint-attr-everywhere-late.rs:187:65
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:182:17
+ --> $DIR/lint-attr-everywhere-late.rs:187:17
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
- --> $DIR/lint-attr-everywhere-late.rs:184:52
+ --> $DIR/lint-attr-everywhere-late.rs:189:52
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
- --> $DIR/lint-attr-everywhere-late.rs:184:72
+ --> $DIR/lint-attr-everywhere-late.rs:189:72
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:184:24
+ --> $DIR/lint-attr-everywhere-late.rs:189:24
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 31 previous errors
+error: aborting due to 32 previous errors
diff --git a/tests/ui/lint/lint-match-arms-2.rs b/tests/ui/lint/lint-match-arms-2.rs
new file mode 100644
index 0000000..0c11463
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.rs
@@ -0,0 +1,24 @@
+#![feature(if_let_guard)]
+#![allow(unused, non_snake_case)]
+
+enum E {
+ A,
+}
+
+#[allow(bindings_with_variant_name, irrefutable_let_patterns)]
+fn foo() {
+ match E::A {
+ #[deny(bindings_with_variant_name)]
+ A => {}
+ //~^ ERROR pattern binding `A` is named the same as one of the variants of the type `E`
+ }
+
+ match &E::A {
+ #[deny(irrefutable_let_patterns)]
+ a if let b = a => {}
+ //~^ ERROR irrefutable `if let` guard pattern
+ _ => {}
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/lint/lint-match-arms-2.stderr b/tests/ui/lint/lint-match-arms-2.stderr
new file mode 100644
index 0000000..062d5c1
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.stderr
@@ -0,0 +1,29 @@
+error[E0170]: pattern binding `A` is named the same as one of the variants of the type `E`
+ --> $DIR/lint-match-arms-2.rs:12:9
+ |
+LL | A => {}
+ | ^ help: to match on the variant, qualify the path: `E::A`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-match-arms-2.rs:11:16
+ |
+LL | #[deny(bindings_with_variant_name)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable `if let` guard pattern
+ --> $DIR/lint-match-arms-2.rs:18:18
+ |
+LL | a if let b = a => {}
+ | ^
+ |
+ = note: this pattern will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
+note: the lint level is defined here
+ --> $DIR/lint-match-arms-2.rs:17:16
+ |
+LL | #[deny(irrefutable_let_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs
new file mode 100644
index 0000000..0cade7f
--- /dev/null
+++ b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: -Dunused_attributes
+
+#![deny(unused_crate_dependencies)]
+#![feature(lint_reasons)]
+
+fn main() {}
diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
index 293fdca..c9b16e4 100644
--- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
+++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
@@ -5,7 +5,6 @@
drop(b);
b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
//~| NOTE cannot assign twice to immutable
- //~| NOTE in this expansion of desugaring of drop and replace
drop(b);
}
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
index e88e244..b1db05a 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
@@ -5,7 +5,7 @@
// needs-unwind Asserting on contents of error message
#![allow(path_statements, unused_allocation)]
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
macro_rules! test {
(
@@ -51,6 +51,7 @@
const FOO: Foo = Foo { bar: 1 };
+
#[derive(Clone, Copy, Debug, PartialEq)]
struct Foo {
bar: i32
@@ -83,9 +84,18 @@
// cast
[ elem as i32 == 3 ] => "Assertion failed: elem as i32 == 3\nWith captures:\n elem = 1\n"
+ // if
+ [ if elem == 3 { true } else { false } ] => "Assertion failed: if elem == 3 { true } else { false }\nWith captures:\n elem = 1\n"
+
// index
[ [1i32, 1][elem as usize] == 3 ] => "Assertion failed: [1i32, 1][elem as usize] == 3\nWith captures:\n elem = 1\n"
+ // let
+ [ if let 3 = elem { true } else { false } ] => "Assertion failed: if let 3 = elem { true } else { false }\nWith captures:\n elem = 1\n"
+
+ // match
+ [ match elem { 3 => true, _ => false, } ] => "Assertion failed: match elem { 3 => true, _ => false, }\nWith captures:\n elem = 1\n"
+
// method call
[ FOO.add(elem, elem) == 3 ] => "Assertion failed: FOO.add(elem, elem) == 3\nWith captures:\n elem = 1\n"
@@ -107,77 +117,4 @@
// unary
[ -elem == -3 ] => "Assertion failed: -elem == -3\nWith captures:\n elem = 1\n"
);
-
- // ***** Disallowed *****
-
- tests!(
- let mut elem = 1i32;
-
- // assign
- [ { let local = elem; local } == 3 ] => "Assertion failed: { let local = elem; local } == 3"
-
- // assign op
- [ { elem += 1; elem } == 3 ] => "Assertion failed: { elem += 1; elem } == 3"
-
- // async
- [ { let _ = async { elem }; elem } == 3 ] => "Assertion failed: { let _ = async { elem }; elem } == 3"
-
- // await
-
- // block
- [ { elem } == 3 ] => "Assertion failed: { elem } == 3"
-
- // break
- [ loop { break elem; } == 3 ] => "Assertion failed: loop { break elem; } == 3"
-
- // closure
- [(|| elem)() == 3 ] => "Assertion failed: (|| elem)() == 3"
-
- // const block
-
- // continue
-
- // err
-
- // field
- [ FOO.bar == 3 ] => "Assertion failed: FOO.bar == 3"
-
- // for loop
- [ { for _ in 0..elem { elem; } elem } == 3 ] => "Assertion failed: { for _ in 0..elem { elem; } elem } == 3"
-
- // if
- [ if true { elem } else { elem } == 3 ] => "Assertion failed: if true { elem } else { elem } == 3"
-
- // inline asm
-
- // let
- [ if let true = true { elem } else { elem } == 3 ] => "Assertion failed: if let true = true { elem } else { elem } == 3"
-
- // lit
-
- // loop
- [ loop { elem; break elem; } == 3 ] => "Assertion failed: loop { elem; break elem; } == 3"
-
- // mac call
-
- // match
- [ match elem { _ => elem } == 3 ] => "Assertion failed: (match elem { _ => elem, }) == 3"
-
- // ret
- [ (|| { return elem; })() == 3 ] => "Assertion failed: (|| { return elem; })() == 3"
-
- // try
- [ (|| { Some(Some(elem)?) })() == Some(3) ] => "Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)"
-
- // try block
-
- // underscore
-
- // while
- [ { while false { elem; break; } elem } == 3 ] => "Assertion failed: { while false { elem; break; } elem } == 3"
-
- // yeet
-
- // yield
- );
}
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
index d46f396..fcf4f36 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
@@ -4,7 +4,7 @@
// run-pass
// needs-unwind Asserting on contents of error message
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
extern crate common;
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
index 6a1435f..c8408d1 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
@@ -1,7 +1,7 @@
// compile-flags: --test
// run-pass
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
#[should_panic(expected = "Custom user message")]
#[test]
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
index 1f5a29a..0e3c14a 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@@ -3,7 +3,7 @@
// run-pass
// needs-unwind Asserting on contents of error message
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
extern crate common;
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
index 01860ad..0d2518d 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
@@ -2,7 +2,7 @@
// ignore-tidy-linelength
// run-pass
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
use std::fmt::{Debug, Formatter};
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
index 5ec84b0..57b79a5 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
@@ -1,7 +1,7 @@
// check-pass
// compile-flags: -Z unpretty=expanded
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
fn arbitrary_consuming_method_for_demonstration_purposes() {
let elem = 1i32;
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index b69b5bc..66321bc 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -3,7 +3,7 @@
// check-pass
// compile-flags: -Z unpretty=expanded
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
diff --git a/tests/ui/methods/call_method_unknown_pointee.rs b/tests/ui/methods/call_method_unknown_pointee.rs
new file mode 100644
index 0000000..fe4275f
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_pointee.rs
@@ -0,0 +1,28 @@
+// edition: 2018
+
+// tests that the pointee type of a raw pointer must be known to call methods on it
+// see also: `tests/ui/editions/edition-raw-pointer-method-2018.rs`
+
+fn main() {
+ let val = 1_u32;
+ let ptr = &val as *const u32;
+ unsafe {
+ let _a: i32 = (ptr as *const _).read();
+ //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+ let b = ptr as *const _;
+ let _b: u8 = b.read();
+ //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+ let _c = (ptr as *const u8).read(); // we know the type here
+ }
+
+ let mut val = 2_u32;
+ let ptr = &mut val as *mut u32;
+ unsafe {
+ let _a: i32 = (ptr as *mut _).read();
+ //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+ let b = ptr as *mut _;
+ b.write(10);
+ //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+ (ptr as *mut i32).write(1000); // we know the type here
+ }
+}
diff --git a/tests/ui/methods/call_method_unknown_pointee.stderr b/tests/ui/methods/call_method_unknown_pointee.stderr
new file mode 100644
index 0000000..84ecf04
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_pointee.stderr
@@ -0,0 +1,27 @@
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+ --> $DIR/call_method_unknown_pointee.rs:10:41
+ |
+LL | let _a: i32 = (ptr as *const _).read();
+ | ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+ --> $DIR/call_method_unknown_pointee.rs:13:24
+ |
+LL | let _b: u8 = b.read();
+ | ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+ --> $DIR/call_method_unknown_pointee.rs:21:39
+ |
+LL | let _a: i32 = (ptr as *mut _).read();
+ | ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+ --> $DIR/call_method_unknown_pointee.rs:24:11
+ |
+LL | b.write(10);
+ | ^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0699`.
diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr
index 5fed903..f7bf858 100644
--- a/tests/ui/never_type/exhaustive_patterns.stderr
+++ b/tests/ui/never_type/exhaustive_patterns.stderr
@@ -14,6 +14,7 @@
LL | A(A),
LL | B(inner::Wrapper<B>),
| - not covered
+ = note: pattern `Either::B(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
= note: the matched value is of type `Either<(), !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5a145ef..49b6dfc 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error: unreachable pattern
- --> $DIR/empty-match.rs:37:9
+ --> $DIR/empty-match.rs:58:9
|
LL | _ => {},
| ^
@@ -11,37 +11,52 @@
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/empty-match.rs:40:9
+ --> $DIR/empty-match.rs:61:9
|
LL | _ if false => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:47:9
+ --> $DIR/empty-match.rs:68:9
|
LL | _ => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:50:9
+ --> $DIR/empty-match.rs:71:9
|
LL | _ if false => {},
| ^
+error[E0005]: refutable pattern in local binding
+ --> $DIR/empty-match.rs:76:9
+ |
+LL | let None = x;
+ | ^^^^ pattern `Some(_)` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
+ = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+ |
+LL | if let None = x { todo!() };
+ | ++ +++++++++++
+
error: unreachable pattern
- --> $DIR/empty-match.rs:57:9
+ --> $DIR/empty-match.rs:88:9
|
LL | _ => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:60:9
+ --> $DIR/empty-match.rs:91:9
|
LL | _ if false => {},
| ^
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
- --> $DIR/empty-match.rs:78:20
+ --> $DIR/empty-match.rs:109:20
|
LL | match_no_arms!(0u8);
| ^^^
@@ -50,13 +65,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
- --> $DIR/empty-match.rs:79:20
+ --> $DIR/empty-match.rs:111:20
|
LL | match_no_arms!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^
|
note: `NonEmptyStruct1` defined here
- --> $DIR/empty-match.rs:14:8
+ --> $DIR/empty-match.rs:15:8
|
LL | struct NonEmptyStruct1;
| ^^^^^^^^^^^^^^^
@@ -64,13 +79,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
- --> $DIR/empty-match.rs:80:20
+ --> $DIR/empty-match.rs:113:20
|
LL | match_no_arms!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyStruct2` defined here
- --> $DIR/empty-match.rs:15:8
+ --> $DIR/empty-match.rs:18:8
|
LL | struct NonEmptyStruct2(bool);
| ^^^^^^^^^^^^^^^
@@ -78,13 +93,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
- --> $DIR/empty-match.rs:81:20
+ --> $DIR/empty-match.rs:115:20
|
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyUnion1` defined here
- --> $DIR/empty-match.rs:16:7
+ --> $DIR/empty-match.rs:21:7
|
LL | union NonEmptyUnion1 {
| ^^^^^^^^^^^^^^
@@ -92,13 +107,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
- --> $DIR/empty-match.rs:82:20
+ --> $DIR/empty-match.rs:117:20
|
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyUnion2` defined here
- --> $DIR/empty-match.rs:19:7
+ --> $DIR/empty-match.rs:26:7
|
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
@@ -106,13 +121,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:83:20
+ --> $DIR/empty-match.rs:119:20
|
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
|
note: `NonEmptyEnum1` defined here
- --> $DIR/empty-match.rs:24:5
+ --> $DIR/empty-match.rs:33:5
|
LL | enum NonEmptyEnum1 {
| -------------
@@ -122,31 +137,32 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:84:20
+ --> $DIR/empty-match.rs:122:20
|
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
|
note: `NonEmptyEnum2` defined here
- --> $DIR/empty-match.rs:27:5
+ --> $DIR/empty-match.rs:40:5
|
LL | enum NonEmptyEnum2 {
| -------------
LL | Foo(bool),
| ^^^ not covered
+...
LL | Bar,
| ^^^ not covered
= note: the matched value is of type `NonEmptyEnum2`
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:85:20
+ --> $DIR/empty-match.rs:125:20
|
LL | match_no_arms!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
|
note: `NonEmptyEnum5` defined here
- --> $DIR/empty-match.rs:30:6
+ --> $DIR/empty-match.rs:49:6
|
LL | enum NonEmptyEnum5 {
| ^^^^^^^^^^^^^
@@ -154,7 +170,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/empty-match.rs:87:24
+ --> $DIR/empty-match.rs:129:24
|
LL | match_guarded_arm!(0u8);
| ^^^ pattern `_` not covered
@@ -167,13 +183,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
- --> $DIR/empty-match.rs:88:24
+ --> $DIR/empty-match.rs:133:24
|
LL | match_guarded_arm!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
|
note: `NonEmptyStruct1` defined here
- --> $DIR/empty-match.rs:14:8
+ --> $DIR/empty-match.rs:15:8
|
LL | struct NonEmptyStruct1;
| ^^^^^^^^^^^^^^^
@@ -185,13 +201,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
- --> $DIR/empty-match.rs:89:24
+ --> $DIR/empty-match.rs:137:24
|
LL | match_guarded_arm!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
|
note: `NonEmptyStruct2` defined here
- --> $DIR/empty-match.rs:15:8
+ --> $DIR/empty-match.rs:18:8
|
LL | struct NonEmptyStruct2(bool);
| ^^^^^^^^^^^^^^^
@@ -203,13 +219,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
- --> $DIR/empty-match.rs:90:24
+ --> $DIR/empty-match.rs:141:24
|
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
|
note: `NonEmptyUnion1` defined here
- --> $DIR/empty-match.rs:16:7
+ --> $DIR/empty-match.rs:21:7
|
LL | union NonEmptyUnion1 {
| ^^^^^^^^^^^^^^
@@ -221,13 +237,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
- --> $DIR/empty-match.rs:91:24
+ --> $DIR/empty-match.rs:145:24
|
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
|
note: `NonEmptyUnion2` defined here
- --> $DIR/empty-match.rs:19:7
+ --> $DIR/empty-match.rs:26:7
|
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
@@ -239,13 +255,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:92:24
+ --> $DIR/empty-match.rs:149:24
|
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
|
note: `NonEmptyEnum1` defined here
- --> $DIR/empty-match.rs:24:5
+ --> $DIR/empty-match.rs:33:5
|
LL | enum NonEmptyEnum1 {
| -------------
@@ -259,18 +275,19 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:93:24
+ --> $DIR/empty-match.rs:153:24
|
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
|
note: `NonEmptyEnum2` defined here
- --> $DIR/empty-match.rs:27:5
+ --> $DIR/empty-match.rs:40:5
|
LL | enum NonEmptyEnum2 {
| -------------
LL | Foo(bool),
| ^^^ not covered
+...
LL | Bar,
| ^^^ not covered
= note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +298,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:94:24
+ --> $DIR/empty-match.rs:157:24
|
LL | match_guarded_arm!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
|
note: `NonEmptyEnum5` defined here
- --> $DIR/empty-match.rs:30:6
+ --> $DIR/empty-match.rs:49:6
|
LL | enum NonEmptyEnum5 {
| ^^^^^^^^^^^^^
@@ -298,6 +315,7 @@
LL + _ => todo!()
|
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 5a145ef..f54a3f3 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,5 +1,5 @@
error: unreachable pattern
- --> $DIR/empty-match.rs:37:9
+ --> $DIR/empty-match.rs:58:9
|
LL | _ => {},
| ^
@@ -11,37 +11,51 @@
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/empty-match.rs:40:9
+ --> $DIR/empty-match.rs:61:9
|
LL | _ if false => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:47:9
+ --> $DIR/empty-match.rs:68:9
|
LL | _ => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:50:9
+ --> $DIR/empty-match.rs:71:9
|
LL | _ if false => {},
| ^
+error[E0005]: refutable pattern in local binding
+ --> $DIR/empty-match.rs:76:9
+ |
+LL | let None = x;
+ | ^^^^ pattern `Some(_)` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+ |
+LL | if let None = x { todo!() };
+ | ++ +++++++++++
+
error: unreachable pattern
- --> $DIR/empty-match.rs:57:9
+ --> $DIR/empty-match.rs:88:9
|
LL | _ => {},
| ^
error: unreachable pattern
- --> $DIR/empty-match.rs:60:9
+ --> $DIR/empty-match.rs:91:9
|
LL | _ if false => {},
| ^
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
- --> $DIR/empty-match.rs:78:20
+ --> $DIR/empty-match.rs:109:20
|
LL | match_no_arms!(0u8);
| ^^^
@@ -50,13 +64,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
- --> $DIR/empty-match.rs:79:20
+ --> $DIR/empty-match.rs:111:20
|
LL | match_no_arms!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^
|
note: `NonEmptyStruct1` defined here
- --> $DIR/empty-match.rs:14:8
+ --> $DIR/empty-match.rs:15:8
|
LL | struct NonEmptyStruct1;
| ^^^^^^^^^^^^^^^
@@ -64,13 +78,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
- --> $DIR/empty-match.rs:80:20
+ --> $DIR/empty-match.rs:113:20
|
LL | match_no_arms!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyStruct2` defined here
- --> $DIR/empty-match.rs:15:8
+ --> $DIR/empty-match.rs:18:8
|
LL | struct NonEmptyStruct2(bool);
| ^^^^^^^^^^^^^^^
@@ -78,13 +92,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
- --> $DIR/empty-match.rs:81:20
+ --> $DIR/empty-match.rs:115:20
|
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyUnion1` defined here
- --> $DIR/empty-match.rs:16:7
+ --> $DIR/empty-match.rs:21:7
|
LL | union NonEmptyUnion1 {
| ^^^^^^^^^^^^^^
@@ -92,13 +106,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
- --> $DIR/empty-match.rs:82:20
+ --> $DIR/empty-match.rs:117:20
|
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `NonEmptyUnion2` defined here
- --> $DIR/empty-match.rs:19:7
+ --> $DIR/empty-match.rs:26:7
|
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
@@ -106,13 +120,13 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:83:20
+ --> $DIR/empty-match.rs:119:20
|
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
|
note: `NonEmptyEnum1` defined here
- --> $DIR/empty-match.rs:24:5
+ --> $DIR/empty-match.rs:33:5
|
LL | enum NonEmptyEnum1 {
| -------------
@@ -122,31 +136,32 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:84:20
+ --> $DIR/empty-match.rs:122:20
|
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
|
note: `NonEmptyEnum2` defined here
- --> $DIR/empty-match.rs:27:5
+ --> $DIR/empty-match.rs:40:5
|
LL | enum NonEmptyEnum2 {
| -------------
LL | Foo(bool),
| ^^^ not covered
+...
LL | Bar,
| ^^^ not covered
= note: the matched value is of type `NonEmptyEnum2`
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:85:20
+ --> $DIR/empty-match.rs:125:20
|
LL | match_no_arms!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
|
note: `NonEmptyEnum5` defined here
- --> $DIR/empty-match.rs:30:6
+ --> $DIR/empty-match.rs:49:6
|
LL | enum NonEmptyEnum5 {
| ^^^^^^^^^^^^^
@@ -154,7 +169,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/empty-match.rs:87:24
+ --> $DIR/empty-match.rs:129:24
|
LL | match_guarded_arm!(0u8);
| ^^^ pattern `_` not covered
@@ -167,13 +182,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
- --> $DIR/empty-match.rs:88:24
+ --> $DIR/empty-match.rs:133:24
|
LL | match_guarded_arm!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
|
note: `NonEmptyStruct1` defined here
- --> $DIR/empty-match.rs:14:8
+ --> $DIR/empty-match.rs:15:8
|
LL | struct NonEmptyStruct1;
| ^^^^^^^^^^^^^^^
@@ -185,13 +200,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
- --> $DIR/empty-match.rs:89:24
+ --> $DIR/empty-match.rs:137:24
|
LL | match_guarded_arm!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
|
note: `NonEmptyStruct2` defined here
- --> $DIR/empty-match.rs:15:8
+ --> $DIR/empty-match.rs:18:8
|
LL | struct NonEmptyStruct2(bool);
| ^^^^^^^^^^^^^^^
@@ -203,13 +218,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
- --> $DIR/empty-match.rs:90:24
+ --> $DIR/empty-match.rs:141:24
|
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
|
note: `NonEmptyUnion1` defined here
- --> $DIR/empty-match.rs:16:7
+ --> $DIR/empty-match.rs:21:7
|
LL | union NonEmptyUnion1 {
| ^^^^^^^^^^^^^^
@@ -221,13 +236,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
- --> $DIR/empty-match.rs:91:24
+ --> $DIR/empty-match.rs:145:24
|
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
|
note: `NonEmptyUnion2` defined here
- --> $DIR/empty-match.rs:19:7
+ --> $DIR/empty-match.rs:26:7
|
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
@@ -239,13 +254,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:92:24
+ --> $DIR/empty-match.rs:149:24
|
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
|
note: `NonEmptyEnum1` defined here
- --> $DIR/empty-match.rs:24:5
+ --> $DIR/empty-match.rs:33:5
|
LL | enum NonEmptyEnum1 {
| -------------
@@ -259,18 +274,19 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:93:24
+ --> $DIR/empty-match.rs:153:24
|
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
|
note: `NonEmptyEnum2` defined here
- --> $DIR/empty-match.rs:27:5
+ --> $DIR/empty-match.rs:40:5
|
LL | enum NonEmptyEnum2 {
| -------------
LL | Foo(bool),
| ^^^ not covered
+...
LL | Bar,
| ^^^ not covered
= note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +297,13 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:94:24
+ --> $DIR/empty-match.rs:157:24
|
LL | match_guarded_arm!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
|
note: `NonEmptyEnum5` defined here
- --> $DIR/empty-match.rs:30:6
+ --> $DIR/empty-match.rs:49:6
|
LL | enum NonEmptyEnum5 {
| ^^^^^^^^^^^^^
@@ -298,6 +314,7 @@
LL + _ => todo!()
|
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index 9cdc041..062241f 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -6,28 +6,49 @@
#![feature(never_type_fallback)]
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![deny(unreachable_patterns)]
+//~^ NOTE the lint level is defined here
extern crate empty;
enum EmptyEnum {}
struct NonEmptyStruct1;
+//~^ NOTE `NonEmptyStruct1` defined here
+//~| NOTE `NonEmptyStruct1` defined here
struct NonEmptyStruct2(bool);
+//~^ NOTE `NonEmptyStruct2` defined here
+//~| NOTE `NonEmptyStruct2` defined here
union NonEmptyUnion1 {
+ //~^ NOTE `NonEmptyUnion1` defined here
+ //~| NOTE `NonEmptyUnion1` defined here
foo: (),
}
union NonEmptyUnion2 {
+ //~^ NOTE `NonEmptyUnion2` defined here
+ //~| NOTE `NonEmptyUnion2` defined here
foo: (),
bar: (),
}
enum NonEmptyEnum1 {
Foo(bool),
+ //~^ NOTE `NonEmptyEnum1` defined here
+ //~| NOTE `NonEmptyEnum1` defined here
+ //~| NOTE not covered
+ //~| NOTE not covered
}
enum NonEmptyEnum2 {
Foo(bool),
+ //~^ NOTE `NonEmptyEnum2` defined here
+ //~| NOTE `NonEmptyEnum2` defined here
+ //~| NOTE not covered
+ //~| NOTE not covered
Bar,
+ //~^ NOTE not covered
+ //~| NOTE not covered
}
enum NonEmptyEnum5 {
+ //~^ NOTE `NonEmptyEnum5` defined here
+ //~| NOTE `NonEmptyEnum5` defined here
V1, V2, V3, V4, V5,
}
@@ -51,6 +72,16 @@
}
}
+fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
+ let None = x;
+ //~^ ERROR refutable pattern in local binding
+ //~| NOTE `let` bindings require an "irrefutable pattern"
+ //~| NOTE for more information, visit
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `Some(_)` not covered
+ //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
+}
+
fn never(x: !) {
match x {} // ok
match x {
@@ -76,20 +107,55 @@
fn main() {
match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+ //~| NOTE the matched value is of type
match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+ //~| NOTE the matched value is of type
match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+ //~| NOTE the matched value is of type
match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+ //~| NOTE the matched value is of type
match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+ //~| NOTE the matched value is of type
match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+ //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+ //~| NOTE the matched value is of type
match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+ //~| NOTE the matched value is of type
match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ //~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`
+ //~| NOTE the matched value is of type
match_guarded_arm!(0u8); //~ ERROR `_` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `_` not covered
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+ //~| NOTE pattern `NonEmptyStruct1` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `NonEmptyStruct2(_)` not covered
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `NonEmptyUnion1 { .. }` not covered
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `NonEmptyUnion2 { .. }` not covered
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+ //~| NOTE in this expansion of match_guarded_arm!
match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ //~| NOTE the matched value is of type
+ //~| NOTE patterns `NonEmptyEnum5::V1`,
+ //~| NOTE in this expansion of match_guarded_arm!
}
diff --git a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs
new file mode 100644
index 0000000..f413b50
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs
@@ -0,0 +1,33 @@
+mod b {
+ pub struct A(u32);
+}
+
+trait Id {
+ type Assoc;
+}
+impl Id for b::A {
+ type Assoc = b::A;
+}
+impl Id for u32 {
+ type Assoc = u32;
+}
+
+
+trait Trait<T> {
+ fn method(&self)
+ where
+ T: Id<Assoc = b::A>;
+}
+
+impl<T: Id> Trait<T> for <T as Id>::Assoc {
+ fn method(&self)
+ where
+ T: Id<Assoc = b::A>,
+ {
+ let Self(a) = self;
+ //~^ ERROR: tuple struct constructor `A` is private
+ println!("{a}");
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr
new file mode 100644
index 0000000..231a4da
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr
@@ -0,0 +1,9 @@
+error[E0603]: tuple struct constructor `A` is private
+ --> $DIR/issue-111220-2-tuple-struct-fields-projection.rs:27:13
+ |
+LL | let Self(a) = self;
+ | ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/privacy/issue-111220-tuple-struct-fields.rs b/tests/ui/privacy/issue-111220-tuple-struct-fields.rs
new file mode 100644
index 0000000..78d35fd
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-tuple-struct-fields.rs
@@ -0,0 +1,46 @@
+mod b {
+ #[derive(Default)]
+ pub struct A(u32);
+}
+
+impl b::A {
+ fn inherent_bypass(&self) {
+ let Self(x) = self;
+ //~^ ERROR: tuple struct constructor `A` is private
+ println!("{x}");
+ }
+}
+
+pub trait B {
+ fn f(&self);
+}
+
+impl B for b::A {
+ fn f(&self) {
+ let Self(a) = self;
+ //~^ ERROR: tuple struct constructor `A` is private
+ println!("{}", a);
+ }
+}
+
+pub trait Projector {
+ type P;
+}
+
+impl Projector for () {
+ type P = b::A;
+}
+
+pub trait Bypass2 {
+ fn f2(&self);
+}
+
+impl Bypass2 for <() as Projector>::P {
+ fn f2(&self) {
+ let Self(a) = self;
+ //~^ ERROR: tuple struct constructor `A` is private
+ println!("{}", a);
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr b/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr
new file mode 100644
index 0000000..17a3237
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr
@@ -0,0 +1,21 @@
+error[E0603]: tuple struct constructor `A` is private
+ --> $DIR/issue-111220-tuple-struct-fields.rs:8:13
+ |
+LL | let Self(x) = self;
+ | ^^^^^^^
+
+error[E0603]: tuple struct constructor `A` is private
+ --> $DIR/issue-111220-tuple-struct-fields.rs:20:13
+ |
+LL | let Self(a) = self;
+ | ^^^^^^^
+
+error[E0603]: tuple struct constructor `A` is private
+ --> $DIR/issue-111220-tuple-struct-fields.rs:40:13
+ |
+LL | let Self(a) = self;
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
index f0105e0..3beb20f 100644
--- a/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
@@ -10,10 +10,12 @@
() if (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
() if (((let 0 = 1))) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
() if true && let 0 = 1 => {}
//~^ ERROR `if let` guards are experimental
@@ -26,16 +28,20 @@
() if (let 0 = 1) && true => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
() if true && (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
() if (let 0 = 1) && (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
() if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
//~^ ERROR `if let` guards are experimental
@@ -47,6 +53,10 @@
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+
() if let Range { start: _, end: _ } = (true..true) && false => {}
//~^ ERROR `if let` guards are experimental
@@ -68,9 +78,11 @@
use_expr!((let 0 = 1 && 0 == 0));
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
use_expr!((let 0 = 1));
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
match () {
#[cfg(FALSE)]
() if let 0 = 1 => {}
diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
index 96fe119..dc182ce 100644
--- a/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
@@ -5,67 +5,67 @@
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:14:18
+ --> $DIR/feature-gate.rs:15:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:26:16
+ --> $DIR/feature-gate.rs:28:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:30:24
+ --> $DIR/feature-gate.rs:33:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:34:16
+ --> $DIR/feature-gate.rs:38:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:34:31
+ --> $DIR/feature-gate.rs:38:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:40:42
+ --> $DIR/feature-gate.rs:46:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:40:55
+ --> $DIR/feature-gate.rs:46:55
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:40:68
+ --> $DIR/feature-gate.rs:46:68
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:68:16
+ --> $DIR/feature-gate.rs:78:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
error: expected expression, found `let` statement
- --> $DIR/feature-gate.rs:71:16
+ --> $DIR/feature-gate.rs:82:16
|
LL | use_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let`
- --> $DIR/feature-gate.rs:80:15
+ --> $DIR/feature-gate.rs:92:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@@ -74,11 +74,154 @@
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
- --> $DIR/feature-gate.rs:61:10
+ --> $DIR/feature-gate.rs:71:10
|
LL | ($e:expr) => {
| ^^^^^^^
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:15:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:15:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:28:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:28:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:33:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:33:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:38:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:38:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:38:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:38:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46:55
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46:68
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:82:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:82:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^^^^^^^
+
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:7:12
|
@@ -90,7 +233,7 @@
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
- --> $DIR/feature-gate.rs:18:12
+ --> $DIR/feature-gate.rs:20:12
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +243,7 @@
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
- --> $DIR/feature-gate.rs:22:12
+ --> $DIR/feature-gate.rs:24:12
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +253,7 @@
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
- --> $DIR/feature-gate.rs:40:12
+ --> $DIR/feature-gate.rs:46:12
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +263,7 @@
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
- --> $DIR/feature-gate.rs:51:12
+ --> $DIR/feature-gate.rs:61:12
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +273,7 @@
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
- --> $DIR/feature-gate.rs:76:12
+ --> $DIR/feature-gate.rs:88:12
|
LL | () if let 0 = 1 => {}
| ^^^^^^^^^^^^
@@ -149,7 +292,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:14:18
+ --> $DIR/feature-gate.rs:15:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^^^^^^^
@@ -158,7 +301,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:18:23
+ --> $DIR/feature-gate.rs:20:23
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^
@@ -167,7 +310,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:22:15
+ --> $DIR/feature-gate.rs:24:15
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^
@@ -176,7 +319,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:26:16
+ --> $DIR/feature-gate.rs:28:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^^^^^^^
@@ -185,7 +328,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:30:24
+ --> $DIR/feature-gate.rs:33:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^^^^^^^
@@ -194,7 +337,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:34:16
+ --> $DIR/feature-gate.rs:38:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@@ -203,7 +346,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:34:31
+ --> $DIR/feature-gate.rs:38:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@@ -212,7 +355,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:40:15
+ --> $DIR/feature-gate.rs:46:15
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@@ -221,7 +364,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:40:28
+ --> $DIR/feature-gate.rs:46:28
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@@ -230,7 +373,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:40:42
+ --> $DIR/feature-gate.rs:46:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@@ -239,7 +382,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:40:55
+ --> $DIR/feature-gate.rs:46:55
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@@ -248,7 +391,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:40:68
+ --> $DIR/feature-gate.rs:46:68
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@@ -257,7 +400,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:51:15
+ --> $DIR/feature-gate.rs:61:15
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -266,7 +409,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:68:16
+ --> $DIR/feature-gate.rs:78:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^^^^^^^
@@ -275,7 +418,7 @@
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
- --> $DIR/feature-gate.rs:71:16
+ --> $DIR/feature-gate.rs:82:16
|
LL | use_expr!((let 0 = 1));
| ^^^^^^^^^
@@ -283,6 +426,6 @@
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
-error: aborting due to 34 previous errors
+error: aborting due to 45 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs
new file mode 100644
index 0000000..e6dee2a
--- /dev/null
+++ b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs
@@ -0,0 +1,23 @@
+#![feature(let_chains)]
+
+fn let_or_guard(x: Result<Option<i32>, ()>) {
+ match x {
+ Ok(opt) if let Some(4) = opt || false => {}
+ //~^ ERROR `let` expressions are not supported here
+ _ => {}
+ }
+}
+
+fn hiding_unsafe_mod(x: Result<Option<i32>, ()>) {
+ match x {
+ Ok(opt)
+ if {
+ unsafe mod a {};
+ //~^ ERROR module cannot be declared unsafe
+ false
+ } => {}
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr
new file mode 100644
index 0000000..2685099
--- /dev/null
+++ b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr
@@ -0,0 +1,21 @@
+error: `let` expressions are not supported here
+ --> $DIR/ast-validate-guards.rs:5:20
+ |
+LL | Ok(opt) if let Some(4) = opt || false => {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/ast-validate-guards.rs:5:38
+ |
+LL | Ok(opt) if let Some(4) = opt || false => {}
+ | ^^
+
+error: module cannot be declared unsafe
+ --> $DIR/ast-validate-guards.rs:15:17
+ |
+LL | unsafe mod a {};
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
index 9f62763..5d8b375 100644
--- a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
+++ b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
@@ -1 +1 @@
-error: The "json" format is only accepted on the nightly compiler
+error: The "json" format is only accepted on the nightly compiler with -Z unstable-options
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
index 531203d..3c7fc74 100644
--- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
+++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
@@ -1,5 +1,8 @@
// compile-flags: -Ztrait-solver=next
+// check-pass
+// (should not pass, should be turned into a coherence-only test)
+
// check that when computing `alias-eq(<() as Foo<u16, T>>::Assoc, <() as Foo<?0, T>>::Assoc)`
// we do not infer `?0 = u8` via the `for<STOP> (): Foo<u8, STOP>` impl or `?0 = u16` by
// relating substs as either could be a valid solution.
@@ -36,7 +39,6 @@
{
// `<() as Foo<u16, STOP>>::Assoc == <() as Foo<_, STOP>>::Assoc`
let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
- //~^ error: type annotations needed
// let _: <() as Foo<u16, T>>::Assoc = output::<u8, T>(); // OK
// let _: <() as Foo<u16, T>>::Assoc = output::<u16, T>(); // OK
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
deleted file mode 100644
index a671233..0000000
--- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0282]: type annotations needed
- --> $DIR/alias_eq_dont_use_normalizes_to_if_substs_eq.rs:38:41
- |
-LL | let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
- | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `output`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
index d4cc380..b036411 100644
--- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
+++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
@@ -1,5 +1,8 @@
// compile-flags: -Ztrait-solver=next
+// check-pass
+// (should not pass, should be turned into a coherence-only test)
+
// check that a `alias-eq(<?0 as TraitB>::Assoc, <T as TraitB>::Assoc)` goal fails.
// FIXME(deferred_projection_equality): add a test that this is true during coherence
@@ -14,7 +17,6 @@
fn bar<T: TraitB>() {
let _: <_ as TraitB>::Assoc = needs_a::<T>();
- //~^ error: type annotations needed
}
fn main() {}
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
deleted file mode 100644
index d063d8f..0000000
--- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0282]: type annotations needed
- --> $DIR/alias_eq_substs_eq_not_intercrate.rs:16:12
- |
-LL | let _: <_ as TraitB>::Assoc = needs_a::<T>();
- | ^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `<_ as TraitB>::Assoc`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
index a6c8631..e7f7fdc 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
@@ -2,7 +2,7 @@
trait One<A> { fn foo(&self) -> A; }
-fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One<()>`
+fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One`
{}
fn main() { }
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
index 59e7bc8..e477247 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
@@ -1,4 +1,4 @@
-error[E0220]: associated type `Output` not found for `One<()>`
+error[E0220]: associated type `Output` not found for `One`
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:16
|
LL | fn foo(_: &dyn One())
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
index 5d7fe3f..eb18b12 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -12,7 +12,7 @@
LL | trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
| ^^^^^ - - -
-error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
+error[E0220]: associated type `Output` not found for `Three`
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
|
LL | fn foo(_: &dyn Three())
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs
index 4b001ac..cfd60a8 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.rs
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs
@@ -16,7 +16,9 @@
}
enum Foo {
+ //~^ NOTE `Foo` defined here
A(foo::SecretlyEmpty),
+ //~^ NOTE not covered
B(foo::NotSoSecretlyEmpty),
C(NotSoSecretlyEmpty),
D(u32, u32),
@@ -27,4 +29,9 @@
let Foo::D(_y, _z) = x;
//~^ ERROR refutable pattern in local binding
//~| `Foo::A(_)` not covered
+ //~| NOTE `let` bindings require an "irrefutable pattern"
+ //~| NOTE for more information
+ //~| NOTE pattern `Foo::A(_)` is currently uninhabited
+ //~| NOTE the matched value is of type `Foo`
+ //~| HELP you might want to use `let else`
}
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
index 8cafea5..daf75f5 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -1,5 +1,5 @@
error[E0005]: refutable pattern in local binding
- --> $DIR/uninhabited-irrefutable.rs:27:9
+ --> $DIR/uninhabited-irrefutable.rs:29:9
|
LL | let Foo::D(_y, _z) = x;
| ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
@@ -11,8 +11,10 @@
|
LL | enum Foo {
| ^^^
+LL |
LL | A(foo::SecretlyEmpty),
| - not covered
+ = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
= note: the matched value is of type `Foo`
help: you might want to use `let else` to handle the variant that isn't matched
|
diff --git a/triagebot.toml b/triagebot.toml
index d7cd3ea..c160c83 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -190,6 +190,7 @@
"src/stage0.json",
"src/tools/compiletest",
"src/tools/tidy",
+ "src/tools/rustdoc-gui-test",
]
[autolabel."T-infra"]
@@ -640,3 +641,4 @@
"/src/tools/rustdoc-themes" = ["rustdoc"]
"/src/tools/tidy" = ["bootstrap"]
"/src/tools/x" = ["bootstrap"]
+"/src/tools/rustdoc-gui-test" = ["bootstrap", "@ozkanonur"]