mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-21 11:23:03 +00:00
Auto merge of #100881 - Dylan-DPC:rollup-q9rr658, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #98200 (Expand potential inner `Or` pattern for THIR) - #99770 (Make some const prop mir-opt tests `unit-test`s) - #99957 (Rework Ipv6Addr::is_global to check for global reachability rather than global scope - rebase) - #100331 (Guarantee `try_reserve` preserves the contents on error) - #100336 (Fix two const_trait_impl issues) - #100713 (Convert diagnostics in parser/expr to SessionDiagnostic) - #100820 (Use pointer `is_aligned*` methods) - #100872 (Add guarantee that Vec::default() does not alloc) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a785176741
@ -41,3 +41,112 @@ parser_switch_mut_let_order =
|
||||
parser_missing_let_before_mut = missing keyword
|
||||
parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
|
||||
parser_use_let_not_var = write `let` instead of `var` to introduce a new variable
|
||||
|
||||
parser_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`
|
||||
|
||||
parser_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
|
||||
|
||||
parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
|
||||
.suggestion = use `!` to perform bitwise not
|
||||
|
||||
parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier
|
||||
.suggestion = use `!` to perform logical negation
|
||||
|
||||
parser_malformed_loop_label = malformed loop label
|
||||
.suggestion = use the correct loop label format
|
||||
|
||||
parser_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
|
||||
.suggestion = remove the lifetime annotation
|
||||
.label = annotated with lifetime here
|
||||
|
||||
parser_field_expression_with_generic = field expressions cannot have generic arguments
|
||||
|
||||
parser_macro_invocation_with_qualified_path = macros cannot use qualified paths
|
||||
|
||||
parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
|
||||
|
||||
parser_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
|
||||
|
||||
parser_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
|
||||
|
||||
parser_float_literal_requires_integer_part = float literals must have an integer part
|
||||
.suggestion = must have an integer part
|
||||
|
||||
parser_invalid_int_literal_width = invalid width `{$width}` for integer literal
|
||||
.help = valid widths are 8, 16, 32, 64 and 128
|
||||
|
||||
parser_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
|
||||
|
||||
parser_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.)
|
||||
|
||||
parser_invalid_float_literal_width = invalid width `{$width}` for float literal
|
||||
.help = valid widths are 32 and 64
|
||||
|
||||
parser_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
|
||||
.label = invalid suffix `{$suffix}`
|
||||
.help = valid suffixes are `f32` and `f64`
|
||||
|
||||
parser_int_literal_too_large = integer literal is too large
|
||||
|
||||
parser_missing_semicolon_before_array = expected `;`, found `[`
|
||||
.suggestion = consider adding `;` here
|
||||
|
||||
parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
|
||||
.label = the `block` fragment is within this context
|
||||
|
||||
parser_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
|
||||
|
||||
parser_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
|
||||
|
||||
parser_expected_expression_found_let = expected expression, found `let` statement
|
||||
|
||||
parser_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
|
||||
|
||||
parser_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
|
||||
|
||||
parser_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
|
||||
|
||||
parser_missing_comma_after_match_arm = expected `,` following `match` arm
|
||||
.suggestion = missing a comma here to end this `match` arm
|
||||
|
||||
parser_catch_after_try = keyword `catch` cannot follow a `try` block
|
||||
.help = try using `match` on the result of the `try` block instead
|
||||
|
||||
parser_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
|
||||
|
||||
parser_eq_field_init = expected `:`, found `=`
|
||||
.suggestion = replace equals symbol with a colon
|
||||
|
||||
parser_dotdotdot = unexpected token: `...`
|
||||
.suggest_exclusive_range = use `..` for an exclusive range
|
||||
.suggest_inclusive_range = or `..=` for an inclusive range
|
||||
|
||||
parser_left_arrow_operator = unexpected token: `<-`
|
||||
.suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
|
||||
|
@ -364,8 +364,8 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
|
||||
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
|
||||
/// works well.
|
||||
#[derive(Clone)]
|
||||
struct PatStack<'p, 'tcx> {
|
||||
pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
|
||||
pub(crate) struct PatStack<'p, 'tcx> {
|
||||
pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
||||
@ -403,6 +403,21 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
// Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix.
|
||||
fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) {
|
||||
if !self.is_empty() && self.head().is_or_pat() {
|
||||
for pat in self.head().iter_fields() {
|
||||
let mut new_patstack = PatStack::from_pattern(pat);
|
||||
new_patstack.pats.extend_from_slice(&self.pats[1..]);
|
||||
if !new_patstack.is_empty() && new_patstack.head().is_or_pat() {
|
||||
new_patstack.expand_and_extend(matrix);
|
||||
} else if !new_patstack.is_empty() {
|
||||
matrix.push(new_patstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This computes `S(self.head().ctor(), self)`. See top of the file for explanations.
|
||||
///
|
||||
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
|
||||
@ -436,7 +451,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
|
||||
/// A 2D matrix.
|
||||
#[derive(Clone)]
|
||||
pub(super) struct Matrix<'p, 'tcx> {
|
||||
patterns: Vec<PatStack<'p, 'tcx>>,
|
||||
pub patterns: Vec<PatStack<'p, 'tcx>>,
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
||||
@ -453,7 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
||||
/// expands it.
|
||||
fn push(&mut self, row: PatStack<'p, 'tcx>) {
|
||||
if !row.is_empty() && row.head().is_or_pat() {
|
||||
self.patterns.extend(row.expand_or_pat());
|
||||
row.expand_and_extend(self);
|
||||
} else {
|
||||
self.patterns.push(row);
|
||||
}
|
||||
|
@ -363,6 +363,349 @@ pub enum InvalidVariableDeclarationSub {
|
||||
UseLetNotVar(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_comparison_operator)]
|
||||
pub(crate) struct InvalidComparisonOperator {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub invalid: String,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidComparisonOperatorSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum InvalidComparisonOperatorSub {
|
||||
#[suggestion_short(
|
||||
parser::use_instead,
|
||||
applicability = "machine-applicable",
|
||||
code = "{correct}"
|
||||
)]
|
||||
Correctable {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
invalid: String,
|
||||
correct: String,
|
||||
},
|
||||
#[label(parser::spaceship_operator_invalid)]
|
||||
Spaceship(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_logical_operator)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidLogicalOperator {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub incorrect: String,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidLogicalOperatorSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum InvalidLogicalOperatorSub {
|
||||
#[suggestion_short(
|
||||
parser::use_amp_amp_for_conjunction,
|
||||
applicability = "machine-applicable",
|
||||
code = "&&"
|
||||
)]
|
||||
Conjunction(#[primary_span] Span),
|
||||
#[suggestion_short(
|
||||
parser::use_pipe_pipe_for_disjunction,
|
||||
applicability = "machine-applicable",
|
||||
code = "||"
|
||||
)]
|
||||
Disjunction(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::tilde_is_not_unary_operator)]
|
||||
pub(crate) struct TildeAsUnaryOperator(
|
||||
#[primary_span]
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "!")]
|
||||
pub Span,
|
||||
);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::unexpected_token_after_not)]
|
||||
pub(crate) struct NotAsNegationOperator {
|
||||
#[primary_span]
|
||||
pub negated: Span,
|
||||
pub negated_desc: String,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "!")]
|
||||
pub not: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::malformed_loop_label)]
|
||||
pub(crate) struct MalformedLoopLabel {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
|
||||
pub span: Span,
|
||||
pub correct_label: Ident,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::lifetime_in_borrow_expression)]
|
||||
pub(crate) struct LifetimeInBorrowExpression {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(applicability = "machine-applicable", code = "")]
|
||||
#[label]
|
||||
pub lifetime_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::field_expression_with_generic)]
|
||||
pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::macro_invocation_with_qualified_path)]
|
||||
pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::unexpected_token_after_label)]
|
||||
pub(crate) struct UnexpectedTokenAfterLabel(
|
||||
#[primary_span]
|
||||
#[label(parser::unexpected_token_after_label)]
|
||||
pub Span,
|
||||
);
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::require_colon_after_labeled_expression)]
|
||||
#[note]
|
||||
pub(crate) struct RequireColonAfterLabeledExpression {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = ": ")]
|
||||
pub label_end: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::do_catch_syntax_removed)]
|
||||
#[note]
|
||||
pub(crate) struct DoCatchSyntaxRemoved {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "try")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::float_literal_requires_integer_part)]
|
||||
pub(crate) struct FloatLiteralRequiresIntegerPart {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = "{correct}")]
|
||||
pub span: Span,
|
||||
pub correct: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_int_literal_width)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidIntLiteralWidth {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub width: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_num_literal_base_prefix)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidNumLiteralBasePrefix {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
|
||||
pub span: Span,
|
||||
pub fixed: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_num_literal_suffix)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidNumLiteralSuffix {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub suffix: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_float_literal_width)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidFloatLiteralWidth {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub width: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_float_literal_suffix)]
|
||||
#[help]
|
||||
pub(crate) struct InvalidFloatLiteralSuffix {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub suffix: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::int_literal_too_large)]
|
||||
pub(crate) struct IntLiteralTooLarge {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_semicolon_before_array)]
|
||||
pub(crate) struct MissingSemicolonBeforeArray {
|
||||
#[primary_span]
|
||||
pub open_delim: Span,
|
||||
#[suggestion_verbose(applicability = "maybe-incorrect", code = ";")]
|
||||
pub semicolon: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::invalid_block_macro_segment)]
|
||||
pub(crate) struct InvalidBlockMacroSegment {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub context: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::if_expression_missing_then_block)]
|
||||
pub(crate) struct IfExpressionMissingThenBlock {
|
||||
#[primary_span]
|
||||
pub if_span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: IfExpressionMissingThenBlockSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum IfExpressionMissingThenBlockSub {
|
||||
#[help(parser::condition_possibly_unfinished)]
|
||||
UnfinishedCondition(#[primary_span] Span),
|
||||
#[help(parser::add_then_block)]
|
||||
AddThenBlock(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::if_expression_missing_condition)]
|
||||
pub(crate) struct IfExpressionMissingCondition {
|
||||
#[primary_span]
|
||||
#[label(parser::condition_label)]
|
||||
pub if_span: Span,
|
||||
#[label(parser::block_label)]
|
||||
pub block_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::expected_expression_found_let)]
|
||||
pub(crate) struct ExpectedExpressionFoundLet {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::expected_else_block)]
|
||||
pub(crate) struct ExpectedElseBlock {
|
||||
#[primary_span]
|
||||
pub first_tok_span: Span,
|
||||
pub first_tok: String,
|
||||
#[label]
|
||||
pub else_span: Span,
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "if ")]
|
||||
pub condition_start: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::outer_attribute_not_allowed_on_if_else)]
|
||||
pub(crate) struct OuterAttributeNotAllowedOnIfElse {
|
||||
#[primary_span]
|
||||
pub last: Span,
|
||||
|
||||
#[label(parser::branch_label)]
|
||||
pub branch_span: Span,
|
||||
|
||||
#[label(parser::ctx_label)]
|
||||
pub ctx_span: Span,
|
||||
pub ctx: String,
|
||||
|
||||
#[suggestion(applicability = "machine-applicable", code = "")]
|
||||
pub attributes: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_in_in_for_loop)]
|
||||
pub(crate) struct MissingInInForLoop {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: MissingInInForLoopSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum MissingInInForLoopSub {
|
||||
// Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
|
||||
#[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")]
|
||||
InNotOf(#[primary_span] Span),
|
||||
#[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")]
|
||||
AddIn(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::missing_comma_after_match_arm)]
|
||||
pub(crate) struct MissingCommaAfterMatchArm {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "machine-applicable", code = ",")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::catch_after_try)]
|
||||
#[help]
|
||||
pub(crate) struct CatchAfterTry {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::comma_after_base_struct)]
|
||||
#[note]
|
||||
pub(crate) struct CommaAfterBaseStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "")]
|
||||
pub comma: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::eq_field_init)]
|
||||
pub(crate) struct EqFieldInit {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(applicability = "machine-applicable", code = ":")]
|
||||
pub eq: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::dotdotdot)]
|
||||
pub(crate) struct DotDotDot {
|
||||
#[primary_span]
|
||||
#[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
|
||||
#[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(parser::left_arrow_operator)]
|
||||
pub(crate) struct LeftArrowOperator {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "< -")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
// SnapshotParser is used to create a snapshot of the parser
|
||||
// without causing duplicate errors being emitted when the `Parser`
|
||||
// is dropped.
|
||||
|
@ -1,4 +1,14 @@
|
||||
use super::diagnostics::SnapshotParser;
|
||||
use super::diagnostics::{
|
||||
CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
|
||||
ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
|
||||
FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
|
||||
IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
|
||||
InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub,
|
||||
LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
|
||||
MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
|
||||
NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression,
|
||||
SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
|
||||
};
|
||||
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
|
||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||
use super::{
|
||||
@ -6,6 +16,11 @@ use super::{
|
||||
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
|
||||
};
|
||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||
use crate::parser::diagnostics::{
|
||||
IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
|
||||
InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix,
|
||||
MissingCommaAfterMatchArm,
|
||||
};
|
||||
|
||||
use core::mem;
|
||||
use rustc_ast::ptr::P;
|
||||
@ -20,9 +35,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
|
||||
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
|
||||
use rustc_ast::{ClosureBinder, StmtKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
||||
use rustc_errors::{Applicability, Diagnostic, PResult};
|
||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::SessionDiagnostic;
|
||||
use rustc_span::source_map::{self, Span, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Pos};
|
||||
@ -216,15 +232,18 @@ impl<'a> Parser<'a> {
|
||||
AssocOp::Equal => "==",
|
||||
AssocOp::NotEqual => "!=",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`"))
|
||||
.span_suggestion_short(
|
||||
sp,
|
||||
&format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
.into();
|
||||
let invalid = format!("{}=", &sugg);
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: invalid.clone(),
|
||||
sub: InvalidComparisonOperatorSub::Correctable {
|
||||
span: sp,
|
||||
invalid,
|
||||
correct: sugg,
|
||||
},
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -234,14 +253,15 @@ impl<'a> Parser<'a> {
|
||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||
{
|
||||
let sp = op.span.to(self.token.span);
|
||||
self.struct_span_err(sp, "invalid comparison operator `<>`")
|
||||
.span_suggestion_short(
|
||||
sp,
|
||||
"`<>` is not a valid comparison operator, use `!=`",
|
||||
"!=",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: "<>".into(),
|
||||
sub: InvalidComparisonOperatorSub::Correctable {
|
||||
span: sp,
|
||||
invalid: "<>".into(),
|
||||
correct: "!=".into(),
|
||||
},
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -251,12 +271,11 @@ impl<'a> Parser<'a> {
|
||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||
{
|
||||
let sp = op.span.to(self.token.span);
|
||||
self.struct_span_err(sp, "invalid comparison operator `<=>`")
|
||||
.span_label(
|
||||
sp,
|
||||
"`<=>` is not a valid comparison operator, use `std::cmp::Ordering`",
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidComparisonOperator {
|
||||
span: sp,
|
||||
invalid: "<=>".into(),
|
||||
sub: InvalidComparisonOperatorSub::Spaceship(sp),
|
||||
});
|
||||
self.bump();
|
||||
}
|
||||
|
||||
@ -430,11 +449,19 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
(Some(op), _) => (op, self.token.span),
|
||||
(None, Some((Ident { name: sym::and, span }, false))) => {
|
||||
self.error_bad_logical_op("and", "&&", "conjunction");
|
||||
self.sess.emit_err(InvalidLogicalOperator {
|
||||
span: self.token.span,
|
||||
incorrect: "and".into(),
|
||||
sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
|
||||
});
|
||||
(AssocOp::LAnd, span)
|
||||
}
|
||||
(None, Some((Ident { name: sym::or, span }, false))) => {
|
||||
self.error_bad_logical_op("or", "||", "disjunction");
|
||||
self.sess.emit_err(InvalidLogicalOperator {
|
||||
span: self.token.span,
|
||||
incorrect: "or".into(),
|
||||
sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
|
||||
});
|
||||
(AssocOp::LOr, span)
|
||||
}
|
||||
_ => return None,
|
||||
@ -442,19 +469,6 @@ impl<'a> Parser<'a> {
|
||||
Some(source_map::respan(span, op))
|
||||
}
|
||||
|
||||
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
|
||||
fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
|
||||
self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator"))
|
||||
.span_suggestion_short(
|
||||
self.token.span,
|
||||
&format!("use `{good}` to perform logical {english}"),
|
||||
good,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Checks if this expression is a successfully parsed statement.
|
||||
fn expr_is_complete(&self, e: &Expr) -> bool {
|
||||
self.restrictions.contains(Restrictions::STMT_EXPR)
|
||||
@ -619,14 +633,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// Recover on `!` suggesting for bitwise negation instead.
|
||||
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.struct_span_err(lo, "`~` cannot be used as a unary operator")
|
||||
.span_suggestion_short(
|
||||
lo,
|
||||
"use `!` to perform bitwise not",
|
||||
"!",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(TildeAsUnaryOperator(lo));
|
||||
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
}
|
||||
@ -652,20 +659,14 @@ impl<'a> Parser<'a> {
|
||||
/// Recover on `not expr` in favor of `!expr`.
|
||||
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
// Emit the error...
|
||||
let not_token = self.look_ahead(1, |t| t.clone());
|
||||
self.struct_span_err(
|
||||
not_token.span,
|
||||
&format!("unexpected {} after identifier", super::token_descr(¬_token)),
|
||||
)
|
||||
.span_suggestion_short(
|
||||
let negated_token = self.look_ahead(1, |t| t.clone());
|
||||
self.sess.emit_err(NotAsNegationOperator {
|
||||
negated: negated_token.span,
|
||||
negated_desc: super::token_descr(&negated_token),
|
||||
// Span the `not` plus trailing whitespace to avoid
|
||||
// trailing whitespace after the `!` in our suggestion
|
||||
self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)),
|
||||
"use `!` to perform logical negation",
|
||||
"!",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
|
||||
});
|
||||
|
||||
// ...and recover!
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
@ -725,14 +726,10 @@ impl<'a> Parser<'a> {
|
||||
match self.parse_labeled_expr(label, false) {
|
||||
Ok(expr) => {
|
||||
type_err.cancel();
|
||||
self.struct_span_err(label.ident.span, "malformed loop label")
|
||||
.span_suggestion(
|
||||
label.ident.span,
|
||||
"use the correct loop label format",
|
||||
label.ident,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(MalformedLoopLabel {
|
||||
span: label.ident.span,
|
||||
correct_label: label.ident,
|
||||
});
|
||||
return Ok(expr);
|
||||
}
|
||||
Err(err) => {
|
||||
@ -910,15 +907,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
|
||||
self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
|
||||
.span_label(lt_span, "annotated with lifetime here")
|
||||
.span_suggestion(
|
||||
lt_span,
|
||||
"remove the lifetime annotation",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
|
||||
}
|
||||
|
||||
/// Parse `mut?` or `raw [ const | mut ]`.
|
||||
@ -1272,11 +1261,7 @@ impl<'a> Parser<'a> {
|
||||
} else {
|
||||
// Field access `expr.f`
|
||||
if let Some(args) = segment.args {
|
||||
self.struct_span_err(
|
||||
args.span(),
|
||||
"field expressions cannot have generic arguments",
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
|
||||
}
|
||||
|
||||
let span = lo.to(self.prev_token.span);
|
||||
@ -1489,7 +1474,7 @@ impl<'a> Parser<'a> {
|
||||
let (span, kind) = if self.eat(&token::Not) {
|
||||
// MACRO INVOCATION expression
|
||||
if qself.is_some() {
|
||||
self.struct_span_err(path.span, "macros cannot use qualified paths").emit();
|
||||
self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
|
||||
}
|
||||
let lo = path.span;
|
||||
let mac = P(MacCall {
|
||||
@ -1535,11 +1520,11 @@ impl<'a> Parser<'a> {
|
||||
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
||||
{
|
||||
// We're probably inside of a `Path<'a>` that needs a turbofish
|
||||
let msg = "expected `while`, `for`, `loop` or `{` after a label";
|
||||
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
|
||||
self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span));
|
||||
consume_colon = false;
|
||||
Ok(self.mk_expr_err(lo))
|
||||
} else {
|
||||
// FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions
|
||||
let msg = "expected `while`, `for`, `loop` or `{` after a label";
|
||||
|
||||
let mut err = self.struct_span_err(self.token.span, msg);
|
||||
@ -1604,25 +1589,16 @@ impl<'a> Parser<'a> {
|
||||
}?;
|
||||
|
||||
if !ate_colon && consume_colon {
|
||||
self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
|
||||
self.sess.emit_err(RequireColonAfterLabeledExpression {
|
||||
span: expr.span,
|
||||
label: lo,
|
||||
label_end: lo.shrink_to_hi(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
|
||||
self.struct_span_err(span, "labeled expression must be followed by `:`")
|
||||
.span_label(lo, "the label")
|
||||
.span_suggestion_short(
|
||||
lo.shrink_to_hi(),
|
||||
"add `:` after the label",
|
||||
": ",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
|
||||
fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
@ -1630,16 +1606,8 @@ impl<'a> Parser<'a> {
|
||||
self.bump(); // `do`
|
||||
self.bump(); // `catch`
|
||||
|
||||
let span_dc = lo.to(self.prev_token.span);
|
||||
self.struct_span_err(span_dc, "found removed `do catch` syntax")
|
||||
.span_suggestion(
|
||||
span_dc,
|
||||
"replace with the new syntax",
|
||||
"try",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("following RFC #2388, the new non-placeholder syntax is `try`")
|
||||
.emit();
|
||||
let span = lo.to(self.prev_token.span);
|
||||
self.sess.emit_err(DoCatchSyntaxRemoved { span });
|
||||
|
||||
self.parse_try_block(lo)
|
||||
}
|
||||
@ -1834,14 +1802,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn error_float_lits_must_have_int_part(&self, token: &Token) {
|
||||
self.struct_span_err(token.span, "float literals must have an integer part")
|
||||
.span_suggestion(
|
||||
token.span,
|
||||
"must have an integer part",
|
||||
pprust::token_to_string(token),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(FloatLiteralRequiresIntegerPart {
|
||||
span: token.span,
|
||||
correct: pprust::token_to_string(token).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
|
||||
@ -1883,28 +1847,11 @@ impl<'a> Parser<'a> {
|
||||
let suf = suf.as_str();
|
||||
if looks_like_width_suffix(&['i', 'u'], &suf) {
|
||||
// If it looks like a width, try to be helpful.
|
||||
let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
|
||||
self.struct_span_err(span, &msg)
|
||||
.help("valid widths are 8, 16, 32, 64 and 128")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
|
||||
} else if let Some(fixed) = fix_base_capitalisation(suf) {
|
||||
let msg = "invalid base prefix for number literal";
|
||||
|
||||
self.struct_span_err(span, msg)
|
||||
.note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"try making the prefix lowercase",
|
||||
fixed,
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
|
||||
} else {
|
||||
let msg = format!("invalid suffix `{suf}` for number literal");
|
||||
self.struct_span_err(span, &msg)
|
||||
.span_label(span, format!("invalid suffix `{suf}`"))
|
||||
.help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
|
||||
}
|
||||
}
|
||||
LitError::InvalidFloatSuffix => {
|
||||
@ -1912,14 +1859,10 @@ impl<'a> Parser<'a> {
|
||||
let suf = suf.as_str();
|
||||
if looks_like_width_suffix(&['f'], suf) {
|
||||
// If it looks like a width, try to be helpful.
|
||||
let msg = format!("invalid width `{}` for float literal", &suf[1..]);
|
||||
self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit();
|
||||
self.sess
|
||||
.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
|
||||
} else {
|
||||
let msg = format!("invalid suffix `{suf}` for float literal");
|
||||
self.struct_span_err(span, &msg)
|
||||
.span_label(span, format!("invalid suffix `{suf}`"))
|
||||
.help("valid suffixes are `f32` and `f64`")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
|
||||
}
|
||||
}
|
||||
LitError::NonDecimalFloat(base) => {
|
||||
@ -1934,7 +1877,7 @@ impl<'a> Parser<'a> {
|
||||
.emit();
|
||||
}
|
||||
LitError::IntTooLarge => {
|
||||
self.struct_span_err(span, "integer literal is too large").emit();
|
||||
self.sess.emit_err(IntLiteralTooLarge { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2046,14 +1989,10 @@ impl<'a> Parser<'a> {
|
||||
.span_to_snippet(snapshot.token.span)
|
||||
.map_or(false, |snippet| snippet == "]") =>
|
||||
{
|
||||
let mut err = self.struct_span_err(open_delim_span, "expected `;`, found `[`");
|
||||
err.span_suggestion_verbose(
|
||||
prev_span.shrink_to_hi(),
|
||||
"consider adding `;` here",
|
||||
';',
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Err(err);
|
||||
return Err(MissingSemicolonBeforeArray {
|
||||
open_delim: open_delim_span,
|
||||
semicolon: prev_span.shrink_to_hi(),
|
||||
}.into_diagnostic(self.sess));
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(err) => err.cancel(),
|
||||
@ -2080,9 +2019,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
if self.token.is_whole_block() {
|
||||
self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
|
||||
.span_label(lo.to(self.token.span), "the `block` fragment is within this context")
|
||||
.emit();
|
||||
self.sess.emit_err(InvalidBlockMacroSegment {
|
||||
span: self.token.span,
|
||||
context: lo.to(self.token.span),
|
||||
});
|
||||
}
|
||||
|
||||
let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
|
||||
@ -2252,11 +2192,19 @@ impl<'a> Parser<'a> {
|
||||
let block = match &mut cond.kind {
|
||||
ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
|
||||
if let ExprKind::Block(_, None) = right.kind => {
|
||||
this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit();
|
||||
self.sess.emit_err(IfExpressionMissingThenBlock {
|
||||
if_span: lo,
|
||||
sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(
|
||||
cond_span.shrink_to_lo().to(*binop_span)
|
||||
),
|
||||
});
|
||||
std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
|
||||
},
|
||||
ExprKind::Block(_, None) => {
|
||||
this.error_missing_if_cond(lo, cond_span).emit();
|
||||
self.sess.emit_err(IfExpressionMissingCondition {
|
||||
if_span: self.sess.source_map().next_point(lo),
|
||||
block_span: self.sess.source_map().start_point(cond_span),
|
||||
});
|
||||
std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
|
||||
}
|
||||
_ => {
|
||||
@ -2274,7 +2222,10 @@ impl<'a> Parser<'a> {
|
||||
if let Some(block) = recover_block_from_condition(self) {
|
||||
block
|
||||
} else {
|
||||
self.error_missing_if_then_block(lo, cond_span, false).emit();
|
||||
self.sess.emit_err(IfExpressionMissingThenBlock {
|
||||
if_span: lo,
|
||||
sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()),
|
||||
});
|
||||
self.mk_block_err(cond_span.shrink_to_hi())
|
||||
}
|
||||
} else {
|
||||
@ -2302,39 +2253,6 @@ impl<'a> Parser<'a> {
|
||||
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
|
||||
}
|
||||
|
||||
fn error_missing_if_then_block(
|
||||
&self,
|
||||
if_span: Span,
|
||||
cond_span: Span,
|
||||
is_unfinished: bool,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut err = self.struct_span_err(
|
||||
if_span,
|
||||
"this `if` expression is missing a block after the condition",
|
||||
);
|
||||
if is_unfinished {
|
||||
err.span_help(cond_span, "this binary operation is possibly unfinished");
|
||||
} else {
|
||||
err.span_help(cond_span.shrink_to_hi(), "add a block here");
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
fn error_missing_if_cond(
|
||||
&self,
|
||||
lo: Span,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let next_span = self.sess.source_map().next_point(lo);
|
||||
let mut err = self.struct_span_err(next_span, "missing condition for `if` expression");
|
||||
err.span_label(next_span, "expected condition here");
|
||||
err.span_label(
|
||||
self.sess.source_map().start_point(span),
|
||||
"if this block is the condition of the `if` expression, then it must be followed by another block"
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
/// Parses the condition of a `if` or `while` expression.
|
||||
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)
|
||||
@ -2350,8 +2268,7 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
|
||||
);
|
||||
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
|
||||
self.struct_span_err(self.token.span, "expected expression, found `let` statement")
|
||||
.emit();
|
||||
self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
|
||||
}
|
||||
|
||||
self.bump(); // Eat `let` token
|
||||
@ -2389,15 +2306,12 @@ impl<'a> Parser<'a> {
|
||||
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
|
||||
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
|
||||
{
|
||||
self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}"))
|
||||
.span_label(else_span, "expected an `if` or a block after this `else`")
|
||||
.span_suggestion(
|
||||
cond.span.shrink_to_lo(),
|
||||
"add an `if` if this is the condition of a chained `else if` statement",
|
||||
"if ",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(ExpectedElseBlock {
|
||||
first_tok_span,
|
||||
first_tok,
|
||||
else_span,
|
||||
condition_start: cond.span.shrink_to_lo(),
|
||||
});
|
||||
self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
|
||||
}
|
||||
Err(e) => {
|
||||
@ -2422,16 +2336,18 @@ impl<'a> Parser<'a> {
|
||||
branch_span: Span,
|
||||
attrs: &[ast::Attribute],
|
||||
) {
|
||||
let (span, last) = match attrs {
|
||||
let (attributes, last) = match attrs {
|
||||
[] => return,
|
||||
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
|
||||
};
|
||||
let ctx = if is_ctx_else { "else" } else { "if" };
|
||||
self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
|
||||
.span_label(branch_span, "the attributes are attached to this branch")
|
||||
.span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
|
||||
.span_suggestion(span, "remove the attributes", "", Applicability::MachineApplicable)
|
||||
.emit();
|
||||
self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
|
||||
last,
|
||||
branch_span,
|
||||
ctx_span,
|
||||
ctx: ctx.to_string(),
|
||||
attributes,
|
||||
});
|
||||
}
|
||||
|
||||
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
|
||||
@ -2465,23 +2381,16 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn error_missing_in_for_loop(&mut self) {
|
||||
let (span, msg, sugg) = if self.token.is_ident_named(sym::of) {
|
||||
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
|
||||
// Possibly using JS syntax (#75311).
|
||||
let span = self.token.span;
|
||||
self.bump();
|
||||
(span, "try using `in` here instead", "in")
|
||||
(span, MissingInInForLoopSub::InNotOf)
|
||||
} else {
|
||||
(self.prev_token.span.between(self.token.span), "try adding `in` here", " in ")
|
||||
(self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
|
||||
};
|
||||
self.struct_span_err(span, "missing `in` in `for` loop")
|
||||
.span_suggestion_short(
|
||||
span,
|
||||
msg,
|
||||
sugg,
|
||||
// Has been misleading, at least in the past (closed Issue #48492).
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
|
||||
self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
|
||||
}
|
||||
|
||||
/// Parses a `while` or `while let` expression (`while` token already eaten).
|
||||
@ -2787,17 +2696,9 @@ impl<'a> Parser<'a> {
|
||||
.is_ok();
|
||||
if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
|
||||
err.cancel();
|
||||
this.struct_span_err(
|
||||
hi.shrink_to_hi(),
|
||||
"expected `,` following `match` arm",
|
||||
)
|
||||
.span_suggestion(
|
||||
hi.shrink_to_hi(),
|
||||
"missing a comma here to end this `match` arm",
|
||||
",",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
this.sess.emit_err(MissingCommaAfterMatchArm {
|
||||
span: hi.shrink_to_hi(),
|
||||
});
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@ -2827,13 +2728,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
if self.eat_keyword(kw::Catch) {
|
||||
let mut error = self.struct_span_err(
|
||||
self.prev_token.span,
|
||||
"keyword `catch` cannot follow a `try` block",
|
||||
);
|
||||
error.help("try using `match` on the result of the `try` block instead");
|
||||
error.emit();
|
||||
Err(error)
|
||||
Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess))
|
||||
} else {
|
||||
let span = span_lo.to(body.span);
|
||||
self.sess.gated_spans.gate(sym::try_blocks, span);
|
||||
@ -3082,18 +2977,10 @@ impl<'a> Parser<'a> {
|
||||
if self.token != token::Comma {
|
||||
return;
|
||||
}
|
||||
self.struct_span_err(
|
||||
span.to(self.prev_token.span),
|
||||
"cannot use a comma after the base struct",
|
||||
)
|
||||
.span_suggestion_short(
|
||||
self.token.span,
|
||||
"remove this comma",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note("the base struct must always be the last field")
|
||||
.emit();
|
||||
self.sess.emit_err(CommaAfterBaseStruct {
|
||||
span: span.to(self.prev_token.span),
|
||||
comma: self.token.span,
|
||||
});
|
||||
self.recover_stmt();
|
||||
}
|
||||
|
||||
@ -3139,43 +3026,18 @@ impl<'a> Parser<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
self.struct_span_err(self.token.span, "expected `:`, found `=`")
|
||||
.span_suggestion(
|
||||
field_name.span.shrink_to_hi().to(self.token.span),
|
||||
"replace equals symbol with a colon",
|
||||
":",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(EqFieldInit {
|
||||
span: self.token.span,
|
||||
eq: field_name.span.shrink_to_hi().to(self.token.span),
|
||||
});
|
||||
}
|
||||
|
||||
fn err_dotdotdot_syntax(&self, span: Span) {
|
||||
self.struct_span_err(span, "unexpected token: `...`")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"use `..` for an exclusive range",
|
||||
"..",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.span_suggestion(
|
||||
span,
|
||||
"or `..=` for an inclusive range",
|
||||
"..=",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(DotDotDot { span });
|
||||
}
|
||||
|
||||
fn err_larrow_operator(&self, span: Span) {
|
||||
self.struct_span_err(span, "unexpected token: `<-`")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"if you meant to write a comparison against a negative value, add a \
|
||||
space in between `<` and `-`",
|
||||
"< -",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(LeftArrowOperator { span });
|
||||
}
|
||||
|
||||
fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
|
||||
|
@ -69,9 +69,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
||||
) {
|
||||
let cause =
|
||||
traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc));
|
||||
// for a type to be WF, we do not need to check if const trait predicates satisfy.
|
||||
let param_env = self.param_env.without_const();
|
||||
self.ocx.register_obligation(traits::Obligation::new(
|
||||
cause,
|
||||
self.param_env,
|
||||
param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
|
||||
));
|
||||
}
|
||||
@ -1449,7 +1451,13 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
||||
let wf_obligations =
|
||||
iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
|
||||
traits::wf::predicate_obligations(infcx, wfcx.param_env, wfcx.body_id, p, sp)
|
||||
traits::wf::predicate_obligations(
|
||||
infcx,
|
||||
wfcx.param_env.without_const(),
|
||||
wfcx.body_id,
|
||||
p,
|
||||
sp,
|
||||
)
|
||||
});
|
||||
|
||||
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
|
||||
|
@ -1010,7 +1010,8 @@ impl<T> BinaryHeap<T> {
|
||||
/// current length. The allocator may reserve more space to speculatively
|
||||
/// avoid frequent allocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional` if it returns
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient.
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient. This method
|
||||
/// preserves the contents even if an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -794,7 +794,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
/// in the given deque. The collection may reserve more space to speculatively avoid
|
||||
/// frequent reallocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional` if it returns
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient.
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient. This method
|
||||
/// preserves the contents even if an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -1080,7 +1080,8 @@ impl String {
|
||||
/// current length. The allocator may reserve more space to speculatively
|
||||
/// avoid frequent allocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional` if it returns
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient.
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient. This method
|
||||
/// preserves the contents even if an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -148,7 +148,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
if self.ptr as *const _ == self.end {
|
||||
if self.ptr == self.end {
|
||||
None
|
||||
} else if mem::size_of::<T>() == 0 {
|
||||
// purposefully don't use 'ptr.offset' because for
|
||||
|
@ -875,7 +875,8 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
/// in the given `Vec<T>`. The collection may reserve more space to speculatively avoid
|
||||
/// frequent reallocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional` if it returns
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient.
|
||||
/// `Ok(())`. Does nothing if capacity is already sufficient. This method
|
||||
/// preserves the contents even if an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
@ -2927,6 +2928,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec<T, A> {
|
||||
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
|
||||
impl<T> const Default for Vec<T> {
|
||||
/// Creates an empty `Vec<T>`.
|
||||
///
|
||||
/// The vector will not allocate until elements are pushed onto it.
|
||||
fn default() -> Vec<T> {
|
||||
Vec::new()
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#![feature(const_str_from_utf8)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(panic_update_hook)]
|
||||
#![feature(pointer_is_aligned)]
|
||||
#![feature(slice_flatten)]
|
||||
#![feature(thin_box)]
|
||||
#![feature(bench_black_box)]
|
||||
|
@ -48,11 +48,11 @@ fn verify_aligned<T>(ptr: *const T) {
|
||||
// practice these checks are mostly just smoke-detectors for an extremely
|
||||
// broken `ThinBox` impl, since it's an extremely subtle piece of code.
|
||||
let ptr = core::hint::black_box(ptr);
|
||||
let align = core::mem::align_of::<T>();
|
||||
assert!(
|
||||
(ptr.addr() & (align - 1)) == 0 && !ptr.is_null(),
|
||||
"misaligned ThinBox data; valid pointers to `{}` should be aligned to {align}: {ptr:p}",
|
||||
core::any::type_name::<T>(),
|
||||
ptr.is_aligned() && !ptr.is_null(),
|
||||
"misaligned ThinBox data; valid pointers to `{ty}` should be aligned to {align}: {ptr:p}",
|
||||
ty = core::any::type_name::<T>(),
|
||||
align = core::mem::align_of::<T>(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2139,7 +2139,7 @@ pub(crate) use assert_unsafe_precondition;
|
||||
/// Checks whether `ptr` is properly aligned with respect to
|
||||
/// `align_of::<T>()`.
|
||||
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
|
||||
!ptr.is_null() && ptr.addr() % mem::align_of::<T>() == 0
|
||||
!ptr.is_null() && ptr.is_aligned()
|
||||
}
|
||||
|
||||
/// Checks whether the regions of memory starting at `src` and `dst` of size
|
||||
|
@ -290,7 +290,8 @@ impl OsString {
|
||||
/// in the given `OsString`. The string may reserve more space to speculatively avoid
|
||||
/// frequent reallocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
|
||||
/// Does nothing if capacity is already sufficient.
|
||||
/// Does nothing if capacity is already sufficient. This method preserves
|
||||
/// the contents even if an error occurs.
|
||||
///
|
||||
/// See the main `OsString` documentation information about encoding and capacity units.
|
||||
///
|
||||
|
@ -296,6 +296,7 @@
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pointer_is_aligned)]
|
||||
#![feature(portable_simd)]
|
||||
#![feature(prelude_2024)]
|
||||
#![feature(provide_any)]
|
||||
|
@ -620,25 +620,31 @@ impl Ipv4Addr {
|
||||
matches!(self.octets(), [169, 254, ..])
|
||||
}
|
||||
|
||||
/// Returns [`true`] if the address appears to be globally routable.
|
||||
/// See [iana-ipv4-special-registry][ipv4-sr].
|
||||
/// Returns [`true`] if the address appears to be globally reachable
|
||||
/// as specified by the [IANA IPv4 Special-Purpose Address Registry].
|
||||
/// Whether or not an address is practically reachable will depend on your network configuration.
|
||||
///
|
||||
/// The following return [`false`]:
|
||||
/// Most IPv4 addresses are globally reachable;
|
||||
/// unless they are specifically defined as *not* globally reachable.
|
||||
///
|
||||
/// - private addresses (see [`Ipv4Addr::is_private()`])
|
||||
/// - the loopback address (see [`Ipv4Addr::is_loopback()`])
|
||||
/// - the link-local address (see [`Ipv4Addr::is_link_local()`])
|
||||
/// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
|
||||
/// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
|
||||
/// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
|
||||
/// `0.0.0.0/8` block
|
||||
/// - addresses reserved for future protocols, except
|
||||
/// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
|
||||
/// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
|
||||
/// - addresses reserved for networking devices benchmarking (see
|
||||
/// [`Ipv4Addr::is_benchmarking()`])
|
||||
/// Non-exhaustive list of notable addresses that are not globally reachable:
|
||||
///
|
||||
/// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
||||
/// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
|
||||
/// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
|
||||
/// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
|
||||
/// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
|
||||
/// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
|
||||
/// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
|
||||
/// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
|
||||
/// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
|
||||
/// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
|
||||
///
|
||||
/// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
|
||||
///
|
||||
/// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
||||
/// [unspecified address]: Ipv4Addr::UNSPECIFIED
|
||||
/// [broadcast address]: Ipv4Addr::BROADCAST
|
||||
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -647,71 +653,61 @@ impl Ipv4Addr {
|
||||
///
|
||||
/// use std::net::Ipv4Addr;
|
||||
///
|
||||
/// // private addresses are not global
|
||||
/// // Most IPv4 addresses are globally reachable:
|
||||
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
|
||||
///
|
||||
/// // However some addresses have been assigned a special meaning
|
||||
/// // that makes them not globally reachable. Some examples are:
|
||||
///
|
||||
/// // The unspecified address (`0.0.0.0`)
|
||||
/// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
|
||||
///
|
||||
/// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
|
||||
/// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
|
||||
/// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
|
||||
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
|
||||
///
|
||||
/// // the 0.0.0.0/8 block is not global
|
||||
/// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
|
||||
/// // in particular, the unspecified address is not global
|
||||
/// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
|
||||
/// // Addresses in the shared address space (`100.64.0.0/10`)
|
||||
/// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
|
||||
///
|
||||
/// // the loopback address is not global
|
||||
/// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
|
||||
/// // The loopback addresses (`127.0.0.0/8`)
|
||||
/// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
|
||||
///
|
||||
/// // link local addresses are not global
|
||||
/// // Link-local addresses (`169.254.0.0/16`)
|
||||
/// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
|
||||
///
|
||||
/// // the broadcast address is not global
|
||||
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
|
||||
///
|
||||
/// // the address space designated for documentation is not global
|
||||
/// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
|
||||
/// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
|
||||
/// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
|
||||
/// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
|
||||
///
|
||||
/// // shared addresses are not global
|
||||
/// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
|
||||
///
|
||||
/// // addresses reserved for protocol assignment are not global
|
||||
/// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
|
||||
/// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
|
||||
///
|
||||
/// // addresses reserved for future use are not global
|
||||
/// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
|
||||
///
|
||||
/// // addresses reserved for network devices benchmarking are not global
|
||||
/// // Addresses reserved for benchmarking (`198.18.0.0/15`)
|
||||
/// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
|
||||
///
|
||||
/// // All the other addresses are global
|
||||
/// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
|
||||
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
|
||||
/// // Reserved addresses (`240.0.0.0/4`)
|
||||
/// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
|
||||
///
|
||||
/// // The broadcast address (`255.255.255.255`)
|
||||
/// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
|
||||
///
|
||||
/// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn is_global(&self) -> bool {
|
||||
// check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
|
||||
// globally routable addresses in the 192.0.0.0/24 range.
|
||||
if u32::from_be_bytes(self.octets()) == 0xc0000009
|
||||
|| u32::from_be_bytes(self.octets()) == 0xc000000a
|
||||
{
|
||||
return true;
|
||||
}
|
||||
!self.is_private()
|
||||
&& !self.is_loopback()
|
||||
&& !self.is_link_local()
|
||||
&& !self.is_broadcast()
|
||||
&& !self.is_documentation()
|
||||
&& !self.is_shared()
|
||||
!(self.octets()[0] == 0 // "This network"
|
||||
|| self.is_private()
|
||||
|| self.is_shared()
|
||||
|| self.is_loopback()
|
||||
|| self.is_link_local()
|
||||
// addresses reserved for future protocols (`192.0.0.0/24`)
|
||||
&& !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
|
||||
&& !self.is_reserved()
|
||||
&& !self.is_benchmarking()
|
||||
// Make sure the address is not in 0.0.0.0/8
|
||||
&& self.octets()[0] != 0
|
||||
||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
|
||||
|| self.is_documentation()
|
||||
|| self.is_benchmarking()
|
||||
|| self.is_reserved()
|
||||
|| self.is_broadcast())
|
||||
}
|
||||
|
||||
/// Returns [`true`] if this address is part of the Shared Address Space defined in
|
||||
@ -1300,13 +1296,33 @@ impl Ipv6Addr {
|
||||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
|
||||
}
|
||||
|
||||
/// Returns [`true`] if the address appears to be globally routable.
|
||||
/// Returns [`true`] if the address appears to be globally reachable
|
||||
/// as specified by the [IANA IPv6 Special-Purpose Address Registry].
|
||||
/// Whether or not an address is practically reachable will depend on your network configuration.
|
||||
///
|
||||
/// The following return [`false`]:
|
||||
/// Most IPv6 addresses are globally reachable;
|
||||
/// unless they are specifically defined as *not* globally reachable.
|
||||
///
|
||||
/// - the loopback address
|
||||
/// - link-local and unique local unicast addresses
|
||||
/// - interface-, link-, realm-, admin- and site-local multicast addresses
|
||||
/// Non-exhaustive list of notable addresses that are not globally reachable:
|
||||
/// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
|
||||
/// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
|
||||
/// - IPv4-mapped addresses
|
||||
/// - Addresses reserved for benchmarking
|
||||
/// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
|
||||
/// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
|
||||
/// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
|
||||
///
|
||||
/// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
|
||||
///
|
||||
/// Note that an address having global scope is not the same as being globally reachable,
|
||||
/// and there is no direct relation between the two concepts: There exist addresses with global scope
|
||||
/// that are not globally reachable (for example unique local addresses),
|
||||
/// and addresses that are globally reachable without having global scope
|
||||
/// (multicast addresses with non-global scope).
|
||||
///
|
||||
/// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
|
||||
/// [unspecified address]: Ipv6Addr::UNSPECIFIED
|
||||
/// [loopback address]: Ipv6Addr::LOCALHOST
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1315,20 +1331,65 @@ impl Ipv6Addr {
|
||||
///
|
||||
/// use std::net::Ipv6Addr;
|
||||
///
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
|
||||
/// // Most IPv6 addresses are globally reachable:
|
||||
/// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
|
||||
///
|
||||
/// // However some addresses have been assigned a special meaning
|
||||
/// // that makes them not globally reachable. Some examples are:
|
||||
///
|
||||
/// // The unspecified address (`::`)
|
||||
/// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
|
||||
///
|
||||
/// // The loopback address (`::1`)
|
||||
/// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
|
||||
///
|
||||
/// // IPv4-mapped addresses (`::ffff:0:0/96`)
|
||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
|
||||
///
|
||||
/// // Addresses reserved for benchmarking (`2001:2::/48`)
|
||||
/// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
|
||||
///
|
||||
/// // Addresses reserved for documentation (`2001:db8::/32`)
|
||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
|
||||
///
|
||||
/// // Unique local addresses (`fc00::/7`)
|
||||
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
|
||||
///
|
||||
/// // Unicast addresses with link-local scope (`fe80::/10`)
|
||||
/// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
|
||||
///
|
||||
/// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self.multicast_scope() {
|
||||
Some(Ipv6MulticastScope::Global) => true,
|
||||
None => self.is_unicast_global(),
|
||||
_ => false,
|
||||
}
|
||||
!(self.is_unspecified()
|
||||
|| self.is_loopback()
|
||||
// IPv4-mapped Address (`::ffff:0:0/96`)
|
||||
|| matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
|
||||
// IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
|
||||
|| matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
|
||||
// Discard-Only Address Block (`100::/64`)
|
||||
|| matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
|
||||
// IETF Protocol Assignments (`2001::/23`)
|
||||
|| (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
|
||||
&& !(
|
||||
// Port Control Protocol Anycast (`2001:1::1`)
|
||||
u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
|
||||
// Traversal Using Relays around NAT Anycast (`2001:1::2`)
|
||||
|| u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
|
||||
// AMT (`2001:3::/32`)
|
||||
|| matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
|
||||
// AS112-v6 (`2001:4:112::/48`)
|
||||
|| matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
|
||||
// ORCHIDv2 (`2001:20::/28`)
|
||||
|| matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
|
||||
))
|
||||
|| self.is_documentation()
|
||||
|| self.is_unique_local()
|
||||
|| self.is_unicast_link_local())
|
||||
}
|
||||
|
||||
/// Returns [`true`] if this is a unique local address (`fc00::/7`).
|
||||
@ -1525,6 +1586,7 @@ impl Ipv6Addr {
|
||||
&& !self.is_unique_local()
|
||||
&& !self.is_unspecified()
|
||||
&& !self.is_documentation()
|
||||
&& !self.is_benchmarking()
|
||||
}
|
||||
|
||||
/// Returns the address's multicast scope if the address is multicast.
|
||||
|
@ -321,15 +321,15 @@ fn ip_properties() {
|
||||
check!("fe80:ffff::");
|
||||
check!("febf:ffff::");
|
||||
check!("fec0::", global);
|
||||
check!("ff01::", multicast);
|
||||
check!("ff02::", multicast);
|
||||
check!("ff03::", multicast);
|
||||
check!("ff04::", multicast);
|
||||
check!("ff05::", multicast);
|
||||
check!("ff08::", multicast);
|
||||
check!("ff01::", global | multicast);
|
||||
check!("ff02::", global | multicast);
|
||||
check!("ff03::", global | multicast);
|
||||
check!("ff04::", global | multicast);
|
||||
check!("ff05::", global | multicast);
|
||||
check!("ff08::", global | multicast);
|
||||
check!("ff0e::", global | multicast);
|
||||
check!("2001:db8:85a3::8a2e:370:7334", doc);
|
||||
check!("2001:2::ac32:23ff:21", global | benchmarking);
|
||||
check!("2001:2::ac32:23ff:21", benchmarking);
|
||||
check!("102:304:506:708:90a:b0c:d0e:f10", global);
|
||||
}
|
||||
|
||||
@ -609,6 +609,60 @@ fn ipv6_properties() {
|
||||
|
||||
check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
|
||||
|
||||
check!(
|
||||
"::ffff:127.0.0.1",
|
||||
&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
|
||||
unicast_global
|
||||
);
|
||||
|
||||
check!(
|
||||
"64:ff9b:1::",
|
||||
&[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
unicast_global
|
||||
);
|
||||
|
||||
check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
|
||||
|
||||
check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
|
||||
|
||||
check!(
|
||||
"2001:1::1",
|
||||
&[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!(
|
||||
"2001:1::2",
|
||||
&[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!(
|
||||
"2001:3::",
|
||||
&[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!(
|
||||
"2001:4:112::",
|
||||
&[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!(
|
||||
"2001:20::",
|
||||
&[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
|
||||
|
||||
check!(
|
||||
"2001:200::",
|
||||
&[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
global | unicast_global
|
||||
);
|
||||
|
||||
check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
|
||||
|
||||
check!(
|
||||
@ -666,21 +720,37 @@ fn ipv6_properties() {
|
||||
check!(
|
||||
"ff01::",
|
||||
&[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_interface_local
|
||||
multicast_interface_local | global
|
||||
);
|
||||
|
||||
check!("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_link_local);
|
||||
check!(
|
||||
"ff02::",
|
||||
&[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_link_local | global
|
||||
);
|
||||
|
||||
check!("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_realm_local);
|
||||
check!(
|
||||
"ff03::",
|
||||
&[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_realm_local | global
|
||||
);
|
||||
|
||||
check!("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_admin_local);
|
||||
check!(
|
||||
"ff04::",
|
||||
&[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_admin_local | global
|
||||
);
|
||||
|
||||
check!("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_site_local);
|
||||
check!(
|
||||
"ff05::",
|
||||
&[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_site_local | global
|
||||
);
|
||||
|
||||
check!(
|
||||
"ff08::",
|
||||
&[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
multicast_organization_local
|
||||
multicast_organization_local | global
|
||||
);
|
||||
|
||||
check!(
|
||||
@ -698,7 +768,7 @@ fn ipv6_properties() {
|
||||
check!(
|
||||
"2001:2::ac32:23ff:21",
|
||||
&[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
|
||||
global | unicast_global | benchmarking
|
||||
benchmarking
|
||||
);
|
||||
|
||||
check!(
|
||||
|
@ -117,7 +117,7 @@ pub unsafe trait UserSafe {
|
||||
/// * the pointer is null.
|
||||
/// * the pointed-to range is not in user memory.
|
||||
unsafe fn check_ptr(ptr: *const Self) {
|
||||
let is_aligned = |p: *const u8| -> bool { 0 == p.addr() & (Self::align_of() - 1) };
|
||||
let is_aligned = |p: *const u8| -> bool { p.is_aligned_to(Self::align_of()) };
|
||||
|
||||
assert!(is_aligned(ptr as *const u8));
|
||||
assert!(is_user_range(ptr as _, mem::size_of_val(unsafe { &*ptr })));
|
||||
@ -386,7 +386,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
|
||||
unsafe {
|
||||
copy_bytewise_to_userspace(src, dst, len);
|
||||
}
|
||||
} else if len % 8 == 0 && dst as usize % 8 == 0 {
|
||||
} else if len % 8 == 0 && dst.is_aligned_to(8) {
|
||||
// Copying 8-byte aligned quadwords: copy quad word per quad word
|
||||
unsafe {
|
||||
copy_quadwords(src, dst, len);
|
||||
|
@ -236,7 +236,8 @@ impl Wtf8Buf {
|
||||
/// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid
|
||||
/// frequent reallocations. After calling `try_reserve`, capacity will be
|
||||
/// greater than or equal to `self.len() + additional`. Does nothing if
|
||||
/// capacity is already sufficient.
|
||||
/// capacity is already sufficient. This method preserves the contents even
|
||||
/// if an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -24,7 +24,7 @@
|
||||
+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
|
||||
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
|
||||
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
|
||||
nop; // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR aggregate.main.ConstProp.diff
|
||||
|
@ -18,11 +18,12 @@
|
||||
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
|
||||
StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32
|
||||
_3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32
|
||||
_4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -30,7 +31,7 @@
|
||||
+ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34
|
||||
StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34
|
||||
nop; // scope 0 at $DIR/array_index.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -18,11 +18,12 @@
|
||||
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
|
||||
StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32
|
||||
_3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32
|
||||
_4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -30,7 +31,7 @@
|
||||
+ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
|
||||
StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34
|
||||
StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34
|
||||
nop; // scope 0 at $DIR/array_index.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
// EMIT_MIR array_index.main.ConstProp.diff
|
||||
|
@ -24,10 +24,9 @@
|
||||
StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
|
||||
- _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
|
||||
- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
|
||||
+ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -38,14 +37,13 @@
|
||||
+ _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
+ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
_2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
|
||||
StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
|
||||
nop; // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
|
||||
_0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
|
||||
StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
|
||||
StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
|
||||
return; // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
|
||||
#[allow(unconditional_panic)]
|
||||
fn main() {
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -O -Zmir-opt-level=4
|
||||
|
||||
// EMIT_MIR boolean_identities.test.ConstProp.diff
|
||||
|
@ -24,12 +24,11 @@
|
||||
StorageLive(_3); // scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
- _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
+ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
+ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
+ _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
_6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
|
||||
// mir::Constant
|
||||
// + span: $DIR/boxes.rs:12:14: 12:22
|
||||
// + span: $DIR/boxes.rs:13:14: 13:22
|
||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
@ -53,7 +52,7 @@
|
||||
|
||||
bb2: {
|
||||
StorageDead(_3); // scope 0 at $DIR/boxes.rs:+1:26: +1:27
|
||||
nop; // scope 0 at $DIR/boxes.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/boxes.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/boxes.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/boxes.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -O
|
||||
// ignore-emscripten compiled with panic=abort by default
|
||||
// ignore-wasm32
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10
|
||||
- _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:+3:13: +3:24
|
||||
+ _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24
|
||||
nop; // scope 0 at $DIR/cast.rs:+0:11: +4:2
|
||||
_0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2
|
||||
StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2
|
||||
StorageDead(_1); // scope 0 at $DIR/cast.rs:+4:1: +4:2
|
||||
return; // scope 0 at $DIR/cast.rs:+4:2: +4:2
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// EMIT_MIR cast.main.ConstProp.diff
|
||||
|
||||
fn main() {
|
||||
|
@ -20,7 +20,7 @@
|
||||
bb1: {
|
||||
- _1 = move (_2.0: u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
|
||||
+ _1 = const 2_u32; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
|
||||
nop; // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/checked_add.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/checked_add.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -C overflow-checks=on
|
||||
|
||||
// EMIT_MIR checked_add.main.ConstProp.diff
|
||||
|
@ -18,7 +18,7 @@
|
||||
StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
|
||||
_3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
|
||||
// mir::Constant
|
||||
// + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
|
||||
// + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16
|
||||
// + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
|
||||
_2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
|
||||
_1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39
|
||||
@ -29,14 +29,14 @@
|
||||
_5 = _1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11
|
||||
_4 = read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12
|
||||
// mir::Constant
|
||||
// + span: $DIR/const_prop_fails_gracefully.rs:8:5: 8:9
|
||||
// + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9
|
||||
// + literal: Const { ty: fn(usize) {read}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12
|
||||
StorageDead(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13
|
||||
nop; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
|
||||
_0 = const (); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
|
||||
StorageDead(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2
|
||||
return; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
#[inline(never)]
|
||||
fn read(_: usize) { }
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -Zmir-opt-level=1
|
||||
|
||||
trait NeedsDrop:Sized{
|
||||
const NEEDS:bool=std::mem::needs_drop::<Self>();
|
||||
trait NeedsDrop: Sized {
|
||||
const NEEDS: bool = std::mem::needs_drop::<Self>();
|
||||
}
|
||||
|
||||
impl<This> NeedsDrop for This{}
|
||||
impl<This> NeedsDrop for This {}
|
||||
|
||||
// EMIT_MIR control_flow_simplification.hello.ConstProp.diff
|
||||
// EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir
|
||||
|
@ -44,7 +44,7 @@
|
||||
_1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
|
||||
nop; // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
_1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
|
||||
nop; // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -O
|
||||
|
||||
// FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with
|
||||
|
@ -18,14 +18,14 @@
|
||||
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
+ _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25
|
||||
+ _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _1 = move (_3.0: u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
+ _1 = const 3_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
|
||||
StorageDead(_2); // scope 0 at $DIR/indirect.rs:+1:28: +1:29
|
||||
nop; // scope 0 at $DIR/indirect.rs:+0:11: +2:2
|
||||
_0 = const (); // scope 0 at $DIR/indirect.rs:+0:11: +2:2
|
||||
StorageDead(_1); // scope 0 at $DIR/indirect.rs:+2:1: +2:2
|
||||
return; // scope 0 at $DIR/indirect.rs:+2:2: +2:2
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -C overflow-checks=on
|
||||
|
||||
// EMIT_MIR indirect.main.ConstProp.diff
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -Z mir-opt-level=3
|
||||
|
||||
// Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test: ConstProp
|
||||
// compile-flags: -Z mir-opt-level=3
|
||||
|
||||
// This used to ICE in const-prop
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22
|
||||
_1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23
|
||||
// mir::Constant
|
||||
// + span: $DIR/issue-66971.rs:16:5: 16:11
|
||||
// + span: $DIR/issue-66971.rs:17:5: 17:11
|
||||
// + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19
|
||||
_1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20
|
||||
// mir::Constant
|
||||
// + span: $DIR/issue-67019.rs:11:5: 11:9
|
||||
// + span: $DIR/issue-67019.rs:12:5: 12:9
|
||||
// + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O -Zmir-opt-level=4
|
||||
|
||||
// EMIT_MIR mult_by_zero.test.ConstProp.diff
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR mutable_variable.main.ConstProp.diff
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff
|
||||
|
@ -16,7 +16,7 @@
|
||||
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14
|
||||
_1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34
|
||||
// mir::Constant
|
||||
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32
|
||||
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32
|
||||
// + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff
|
||||
|
@ -25,7 +25,7 @@
|
||||
StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
|
||||
_4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
|
||||
// mir::Constant
|
||||
// + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19
|
||||
// + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19
|
||||
// + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) }
|
||||
_3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
|
||||
_1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
static mut STATIC: u32 = 42;
|
||||
|
@ -25,7 +25,7 @@
|
||||
StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
|
||||
_1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18
|
||||
// mir::Constant
|
||||
// + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16
|
||||
// + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16
|
||||
// + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
// EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -C overflow-checks=on
|
||||
|
||||
struct Point {
|
||||
|
@ -18,7 +18,7 @@
|
||||
StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
|
||||
_3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
|
||||
// mir::Constant
|
||||
// + span: $DIR/read_immutable_static.rs:7:13: 7:16
|
||||
// + span: $DIR/read_immutable_static.rs:8:13: 8:16
|
||||
// + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
|
||||
- _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
|
||||
+ _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
|
||||
@ -26,7 +26,7 @@
|
||||
StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
|
||||
_5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
|
||||
// mir::Constant
|
||||
// + span: $DIR/read_immutable_static.rs:7:19: 7:22
|
||||
// + span: $DIR/read_immutable_static.rs:8:19: 8:22
|
||||
// + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
|
||||
- _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
|
||||
- _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// compile-flags: -O
|
||||
|
||||
static FOO: u8 = 2;
|
||||
|
@ -13,7 +13,7 @@
|
||||
StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
_4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
// mir::Constant
|
||||
// + span: $DIR/ref_deref_project.rs:5:6: 5:17
|
||||
// + span: $DIR/ref_deref_project.rs:6:6: 6:17
|
||||
// + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
|
||||
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
|
||||
|
@ -16,7 +16,7 @@
|
||||
- _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
+ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/ref_deref_project.rs:5:6: 5:17
|
||||
+ // + span: $DIR/ref_deref_project.rs:6:6: 6:17
|
||||
+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
|
||||
+ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
|
||||
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
|
||||
|
@ -1,3 +1,4 @@
|
||||
// unit-test
|
||||
// EMIT_MIR ref_deref_project.main.PromoteTemps.diff
|
||||
// EMIT_MIR ref_deref_project.main.ConstProp.diff
|
||||
|
||||
|
11
src/test/ui/or-patterns/inner-or-pat.or3.stderr
Normal file
11
src/test/ui/or-patterns/inner-or-pat.or3.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/inner-or-pat.rs:38:54
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `&str`
|
||||
LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
|
||||
| ^^ expected `str`, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
11
src/test/ui/or-patterns/inner-or-pat.or4.stderr
Normal file
11
src/test/ui/or-patterns/inner-or-pat.or4.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0408]: variable `x` is not bound in all patterns
|
||||
--> $DIR/inner-or-pat.rs:53:37
|
||||
|
|
||||
LL | (x @ "red" | (x @ "blue" | "red")) => {
|
||||
| - ^^^^^ pattern doesn't bind `x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0408`.
|
73
src/test/ui/or-patterns/inner-or-pat.rs
Normal file
73
src/test/ui/or-patterns/inner-or-pat.rs
Normal file
@ -0,0 +1,73 @@
|
||||
// revisions: or1 or2 or3 or4 or5
|
||||
// [or1] run-pass
|
||||
// [or2] run-pass
|
||||
// [or5] run-pass
|
||||
|
||||
#![allow(unreachable_patterns)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
||||
|
||||
fn foo() {
|
||||
let x = "foo";
|
||||
match x {
|
||||
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
|
||||
x @ ("black" | "pink") |
|
||||
x @ ("red" | "blue") => {
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
let x = "foo";
|
||||
match x {
|
||||
x @ ("foo" | "bar") |
|
||||
(x @ "red" | (x @ "blue" | x @ "red")) => {
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(or3)]
|
||||
fn zot() {
|
||||
let x = "foo";
|
||||
match x {
|
||||
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
|
||||
//[or3]~^ ERROR mismatched types
|
||||
x @ ("black" | "pink") |
|
||||
x @ ("red" | "blue") => {
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(or4)]
|
||||
fn hey() {
|
||||
let x = "foo";
|
||||
match x {
|
||||
x @ ("foo" | "bar") |
|
||||
(x @ "red" | (x @ "blue" | "red")) => {
|
||||
//[or4]~^ variable `x` is not bound in all patterns
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn don() {
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
match Foo::A {
|
||||
| _foo @ (Foo::A | Foo::B) => {}
|
||||
Foo::C => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn main(){}
|
29
src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
Normal file
29
src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// revisions: nn ny yn yy
|
||||
// check-pass
|
||||
#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)]
|
||||
|
||||
#[cfg_attr(any(yn, yy), const_trait)]
|
||||
pub trait Index {
|
||||
type Output;
|
||||
}
|
||||
|
||||
#[cfg_attr(any(ny, yy), const_trait)]
|
||||
pub trait IndexMut where Self: Index {
|
||||
const C: <Self as Index>::Output;
|
||||
type Assoc = <Self as Index>::Output;
|
||||
fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
|
||||
}
|
||||
|
||||
impl Index for () { type Output = (); }
|
||||
|
||||
impl const IndexMut for <() as Index>::Output {
|
||||
const C: <Self as Index>::Output = ();
|
||||
type Assoc = <Self as Index>::Output;
|
||||
fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
|
||||
where <Self as Index>::Output:,
|
||||
{}
|
||||
}
|
||||
|
||||
const C: <() as Index>::Output = ();
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user