From a201fab20881499d79e5694ee8f195ce50c5b724 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 17:08:58 +1000 Subject: [PATCH 01/13] Tweak `expand_incomplete_parse` warning. By using `token_descr`, as is done for many other errors, we can get slightly better descriptions in error messages, e.g. "macro expansion ignores token `let` and any following" becomes "macro expansion ignores keyword `let` and any tokens following". This will be more important once invisible delimiters start being mentioned in error messages -- without this commit, that leads to error messages such as "error at ``" because invisible delimiters are pretty printed as an empty string. --- compiler/rustc_expand/messages.ftl | 2 +- compiler/rustc_expand/src/errors.rs | 2 +- compiler/rustc_expand/src/expand.rs | 5 +++-- compiler/rustc_parse/src/parser/mod.rs | 2 +- tests/ui/macros/issue-118786.rs | 2 +- tests/ui/macros/issue-118786.stderr | 2 +- tests/ui/macros/issue-30007.rs | 2 +- tests/ui/macros/issue-30007.stderr | 2 +- tests/ui/macros/issue-54441.rs | 2 +- tests/ui/macros/issue-54441.stderr | 2 +- tests/ui/macros/macro-context.rs | 6 +++--- tests/ui/macros/macro-context.stderr | 6 +++--- tests/ui/macros/macro-in-expression-context.fixed | 2 +- tests/ui/macros/macro-in-expression-context.rs | 2 +- tests/ui/macros/macro-in-expression-context.stderr | 2 +- tests/ui/macros/syntax-error-recovery.rs | 2 +- tests/ui/macros/syntax-error-recovery.stderr | 2 +- tests/ui/parser/macro/macro-expand-to-match-arm.rs | 2 +- tests/ui/parser/macro/macro-expand-to-match-arm.stderr | 2 +- tests/ui/parser/macro/macro-incomplete-parse.rs | 4 ++-- tests/ui/parser/macro/macro-incomplete-parse.stderr | 4 ++-- tests/ui/parser/macro/trait-non-item-macros.rs | 2 +- tests/ui/parser/macro/trait-non-item-macros.stderr | 2 +- tests/ui/proc-macro/attr-invalid-exprs.rs | 4 ++-- tests/ui/proc-macro/attr-invalid-exprs.stderr | 4 ++-- tests/ui/proc-macro/expand-expr.rs | 4 ++-- tests/ui/proc-macro/expand-expr.stderr | 4 ++-- 27 files changed, 39 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index fcf3352bfc597..f26c7c1ba0bc4 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -74,7 +74,7 @@ expand_helper_attribute_name_invalid = `{$name}` cannot be a name of derive helper attribute expand_incomplete_parse = - macro expansion ignores token `{$token}` and any following + macro expansion ignores {$descr} and any tokens following .label = caused by the macro expansion here .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context .suggestion_add_semi = you might be missing a semicolon here diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 5682c574552b4..7bd7c30553913 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -275,7 +275,7 @@ pub(crate) struct UnsupportedKeyValue { pub(crate) struct IncompleteParse<'a> { #[primary_span] pub span: Span, - pub token: Cow<'a, str>, + pub descr: String, #[label] pub label_span: Span, pub macro_path: &'a ast::Path, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5ffafcaa54262..04ac7891023f5 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -21,6 +21,7 @@ use rustc_errors::PResult; use rustc_feature::Features; use rustc_parse::parser::{ AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma, + token_descr, }; use rustc_parse::validate_attr; use rustc_session::lint::BuiltinLintDiag; @@ -1013,7 +1014,7 @@ pub(crate) fn ensure_complete_parse<'a>( span: Span, ) { if parser.token != token::Eof { - let token = pprust::token_to_string(&parser.token); + let descr = token_descr(&parser.token); // Avoid emitting backtrace info twice. let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root()); @@ -1029,7 +1030,7 @@ pub(crate) fn ensure_complete_parse<'a>( parser.dcx().emit_err(IncompleteParse { span: def_site_span, - token, + descr, label_span: span, macro_path, kind_name, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 77ad4fdeeb17b..50a8b6542df4f 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -424,7 +424,7 @@ impl TokenDescription { } } -pub(super) fn token_descr(token: &Token) -> String { +pub fn token_descr(token: &Token) -> String { let name = pprust::token_to_string(token).to_string(); let kind = match (TokenDescription::from_token(token), &token.kind) { diff --git a/tests/ui/macros/issue-118786.rs b/tests/ui/macros/issue-118786.rs index a41372e4ea840..a73b737fe07e4 100644 --- a/tests/ui/macros/issue-118786.rs +++ b/tests/ui/macros/issue-118786.rs @@ -5,7 +5,7 @@ macro_rules! make_macro { ($macro_name:tt) => { macro_rules! $macro_name { - //~^ ERROR macro expansion ignores token `{` and any following + //~^ ERROR macro expansion ignores `{` and any tokens following //~| ERROR cannot find macro `macro_rules` in this scope //~| put a macro name here () => {} diff --git a/tests/ui/macros/issue-118786.stderr b/tests/ui/macros/issue-118786.stderr index 256b742ee160b..7fa5c2b83ddd8 100644 --- a/tests/ui/macros/issue-118786.stderr +++ b/tests/ui/macros/issue-118786.stderr @@ -13,7 +13,7 @@ help: add a semicolon LL | macro_rules! $macro_name; { | + -error: macro expansion ignores token `{` and any following +error: macro expansion ignores `{` and any tokens following --> $DIR/issue-118786.rs:7:34 | LL | macro_rules! $macro_name { diff --git a/tests/ui/macros/issue-30007.rs b/tests/ui/macros/issue-30007.rs index 918a821bae925..e36e47a3e7c23 100644 --- a/tests/ui/macros/issue-30007.rs +++ b/tests/ui/macros/issue-30007.rs @@ -1,5 +1,5 @@ macro_rules! t { - () => ( String ; ); //~ ERROR macro expansion ignores token `;` + () => ( String ; ); //~ ERROR macro expansion ignores `;` } fn main() { diff --git a/tests/ui/macros/issue-30007.stderr b/tests/ui/macros/issue-30007.stderr index f303221cf8aa8..129733ed69aba 100644 --- a/tests/ui/macros/issue-30007.stderr +++ b/tests/ui/macros/issue-30007.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `;` and any following +error: macro expansion ignores `;` and any tokens following --> $DIR/issue-30007.rs:2:20 | LL | () => ( String ; ); diff --git a/tests/ui/macros/issue-54441.rs b/tests/ui/macros/issue-54441.rs index b24d7e1f6bee5..37ab4e636475b 100644 --- a/tests/ui/macros/issue-54441.rs +++ b/tests/ui/macros/issue-54441.rs @@ -1,6 +1,6 @@ macro_rules! m { () => { - let //~ ERROR macro expansion ignores token `let` and any following + let //~ ERROR macro expansion ignores keyword `let` and any tokens following }; } diff --git a/tests/ui/macros/issue-54441.stderr b/tests/ui/macros/issue-54441.stderr index fb2c103139b97..f5f8b8ca2b266 100644 --- a/tests/ui/macros/issue-54441.stderr +++ b/tests/ui/macros/issue-54441.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `let` and any following +error: macro expansion ignores keyword `let` and any tokens following --> $DIR/issue-54441.rs:3:9 | LL | let diff --git a/tests/ui/macros/macro-context.rs b/tests/ui/macros/macro-context.rs index d09fdf118e6f4..a31470263a0a5 100644 --- a/tests/ui/macros/macro-context.rs +++ b/tests/ui/macros/macro-context.rs @@ -1,9 +1,9 @@ // (typeof used because it's surprisingly hard to find an unparsed token after a stmt) macro_rules! m { () => ( i ; typeof ); //~ ERROR expected expression, found reserved keyword `typeof` - //~| ERROR macro expansion ignores token `typeof` - //~| ERROR macro expansion ignores token `;` - //~| ERROR macro expansion ignores token `;` + //~| ERROR macro expansion ignores reserved keyword `typeof` + //~| ERROR macro expansion ignores `;` + //~| ERROR macro expansion ignores `;` //~| ERROR cannot find type `i` in this scope //~| ERROR cannot find value `i` in this scope //~| WARN trailing semicolon in macro diff --git a/tests/ui/macros/macro-context.stderr b/tests/ui/macros/macro-context.stderr index 7785f41594627..4820a43f00c79 100644 --- a/tests/ui/macros/macro-context.stderr +++ b/tests/ui/macros/macro-context.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `;` and any following +error: macro expansion ignores `;` and any tokens following --> $DIR/macro-context.rs:3:15 | LL | () => ( i ; typeof ); @@ -9,7 +9,7 @@ LL | let a: m!(); | = note: the usage of `m!` is likely invalid in type context -error: macro expansion ignores token `typeof` and any following +error: macro expansion ignores reserved keyword `typeof` and any tokens following --> $DIR/macro-context.rs:3:17 | LL | () => ( i ; typeof ); @@ -20,7 +20,7 @@ LL | let i = m!(); | = note: the usage of `m!` is likely invalid in expression context -error: macro expansion ignores token `;` and any following +error: macro expansion ignores `;` and any tokens following --> $DIR/macro-context.rs:3:15 | LL | () => ( i ; typeof ); diff --git a/tests/ui/macros/macro-in-expression-context.fixed b/tests/ui/macros/macro-in-expression-context.fixed index f4d04ca37bf5b..7c830707ffd9d 100644 --- a/tests/ui/macros/macro-in-expression-context.fixed +++ b/tests/ui/macros/macro-in-expression-context.fixed @@ -11,7 +11,7 @@ macro_rules! foo { //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default assert_eq!("B", "B"); } - //~^^ ERROR macro expansion ignores token `assert_eq` and any following + //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following //~| NOTE the usage of `foo!` is likely invalid in expression context } diff --git a/tests/ui/macros/macro-in-expression-context.rs b/tests/ui/macros/macro-in-expression-context.rs index 8921a05637725..da95017aa5f74 100644 --- a/tests/ui/macros/macro-in-expression-context.rs +++ b/tests/ui/macros/macro-in-expression-context.rs @@ -11,7 +11,7 @@ macro_rules! foo { //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default assert_eq!("B", "B"); } - //~^^ ERROR macro expansion ignores token `assert_eq` and any following + //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following //~| NOTE the usage of `foo!` is likely invalid in expression context } diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr index 2eee63f307af9..43419f2678c22 100644 --- a/tests/ui/macros/macro-in-expression-context.stderr +++ b/tests/ui/macros/macro-in-expression-context.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `assert_eq` and any following +error: macro expansion ignores `assert_eq` and any tokens following --> $DIR/macro-in-expression-context.rs:12:9 | LL | assert_eq!("B", "B"); diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index f6178c137db97..016e4def28497 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -10,7 +10,7 @@ macro_rules! values { }; } //~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` -//~| ERROR macro expansion ignores token `(String)` and any following +//~| ERROR macro expansion ignores type `(String)` and any tokens following values!(STRING(1) as (String) => cfg(test),); //~^ ERROR expected one of `!` or `::`, found `` diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 6218bf43a1ef2..3cfbd8ce82b56 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -10,7 +10,7 @@ LL | values!(STRING(1) as (String) => cfg(test),); = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) -error: macro expansion ignores token `(String)` and any following +error: macro expansion ignores type `(String)` and any tokens following --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index db38fa0d7bc65..0e27836b718bc 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -1,7 +1,7 @@ macro_rules! arm { ($pattern:pat => $block:block) => { $pattern => $block - //~^ ERROR macro expansion ignores token `=>` and any following + //~^ ERROR macro expansion ignores `=>` and any tokens following //~| NOTE the usage of `arm!` is likely invalid in pattern context //~| NOTE macros cannot expand to match arms }; diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr index e3e7ff89c8134..1927d80fd724c 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `=>` and any following +error: macro expansion ignores `=>` and any tokens following --> $DIR/macro-expand-to-match-arm.rs:3:18 | LL | $pattern => $block diff --git a/tests/ui/parser/macro/macro-incomplete-parse.rs b/tests/ui/parser/macro/macro-incomplete-parse.rs index 544e4aa7b1b09..612196aa4b276 100644 --- a/tests/ui/parser/macro/macro-incomplete-parse.rs +++ b/tests/ui/parser/macro/macro-incomplete-parse.rs @@ -2,7 +2,7 @@ macro_rules! ignored_item { () => { fn foo() {} fn bar() {} - , //~ ERROR macro expansion ignores token `,` + , //~ ERROR macro expansion ignores `,` } } @@ -13,7 +13,7 @@ macro_rules! ignored_expr { } macro_rules! ignored_pat { - () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` + () => ( 1, 2 ) //~ ERROR macro expansion ignores `,` } ignored_item!(); diff --git a/tests/ui/parser/macro/macro-incomplete-parse.stderr b/tests/ui/parser/macro/macro-incomplete-parse.stderr index 707417b725e9f..096b5f718ae1c 100644 --- a/tests/ui/parser/macro/macro-incomplete-parse.stderr +++ b/tests/ui/parser/macro/macro-incomplete-parse.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `,` and any following +error: macro expansion ignores `,` and any tokens following --> $DIR/macro-incomplete-parse.rs:5:9 | LL | , @@ -20,7 +20,7 @@ LL | ignored_expr!(); | = note: this error originates in the macro `ignored_expr` (in Nightly builds, run with -Z macro-backtrace for more info) -error: macro expansion ignores token `,` and any following +error: macro expansion ignores `,` and any tokens following --> $DIR/macro-incomplete-parse.rs:16:14 | LL | () => ( 1, 2 ) diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs index 97fb564bf6479..e93000193b6e3 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.rs +++ b/tests/ui/parser/macro/trait-non-item-macros.rs @@ -1,7 +1,7 @@ macro_rules! bah { ($a:expr) => { $a - }; //~^ ERROR macro expansion ignores token `2` and any following + }; //~^ ERROR macro expansion ignores expression `2` and any tokens following } trait Bar { diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr index db20e6b24aa03..1a82848377895 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.stderr +++ b/tests/ui/parser/macro/trait-non-item-macros.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores token `2` and any following +error: macro expansion ignores expression `2` and any tokens following --> $DIR/trait-non-item-macros.rs:3:9 | LL | $a diff --git a/tests/ui/proc-macro/attr-invalid-exprs.rs b/tests/ui/proc-macro/attr-invalid-exprs.rs index 3d8806ee80030..ec0b79469a457 100644 --- a/tests/ui/proc-macro/attr-invalid-exprs.rs +++ b/tests/ui/proc-macro/attr-invalid-exprs.rs @@ -13,7 +13,7 @@ fn main() { //~^ ERROR expected expression, found end of macro arguments let _ = #[duplicate] "Hello, world!"; - //~^ ERROR macro expansion ignores token `,` and any following + //~^ ERROR macro expansion ignores `,` and any tokens following let _ = { #[no_output] @@ -22,7 +22,7 @@ fn main() { let _ = { #[duplicate] - //~^ ERROR macro expansion ignores token `,` and any following + //~^ ERROR macro expansion ignores `,` and any tokens following "Hello, world!" }; } diff --git a/tests/ui/proc-macro/attr-invalid-exprs.stderr b/tests/ui/proc-macro/attr-invalid-exprs.stderr index f96939bb6efce..0d500c871453f 100644 --- a/tests/ui/proc-macro/attr-invalid-exprs.stderr +++ b/tests/ui/proc-macro/attr-invalid-exprs.stderr @@ -4,7 +4,7 @@ error: expected expression, found end of macro arguments LL | let _ = #[no_output] "Hello, world!"; | ^^^^^^^^^^^^ -error: macro expansion ignores token `,` and any following +error: macro expansion ignores `,` and any tokens following --> $DIR/attr-invalid-exprs.rs:15:13 | LL | let _ = #[duplicate] "Hello, world!"; @@ -16,7 +16,7 @@ help: you might be missing a semicolon here LL | let _ = #[duplicate]; "Hello, world!"; | + -error: macro expansion ignores token `,` and any following +error: macro expansion ignores `,` and any tokens following --> $DIR/attr-invalid-exprs.rs:24:9 | LL | #[duplicate] diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs index 5f7375d7450d6..e06ddc51a297e 100644 --- a/tests/ui/proc-macro/expand-expr.rs +++ b/tests/ui/proc-macro/expand-expr.rs @@ -114,8 +114,8 @@ expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$` // We get errors reported and recover during macro expansion if the macro // doesn't produce a valid expression. -expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following -expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following +expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores `hello` and any tokens following +expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores `;` and any tokens following // For now, fail if a non-literal expression is expanded. expand_expr_fail!(arbitrary_expression() + "etc"); diff --git a/tests/ui/proc-macro/expand-expr.stderr b/tests/ui/proc-macro/expand-expr.stderr index 2b92472e5ab75..8b1df177cfa6d 100644 --- a/tests/ui/proc-macro/expand-expr.stderr +++ b/tests/ui/proc-macro/expand-expr.stderr @@ -22,7 +22,7 @@ error: expected expression, found `$` LL | expand_expr_fail!(echo_pm!($)); | ^ expected expression -error: macro expansion ignores token `hello` and any following +error: macro expansion ignores `hello` and any tokens following --> $DIR/expand-expr.rs:117:47 | LL | expand_expr_is!("string", echo_tts!("string"; hello)); @@ -34,7 +34,7 @@ help: you might be missing a semicolon here LL | expand_expr_is!("string", echo_tts!("string"; hello);); | + -error: macro expansion ignores token `;` and any following +error: macro expansion ignores `;` and any tokens following --> $DIR/expand-expr.rs:118:44 | LL | expand_expr_is!("string", echo_pm!("string"; hello)); From dd2b027d5d509dd95c5ef6f83ea6283f3e98d5ed Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Jun 2024 12:52:15 +1000 Subject: [PATCH 02/13] Tweak more warnings. Much like the previous commit. I think the removal of "the token" in each message is fine here. There are many more error messages that mention tokens without saying "the token" than those that do say it. --- compiler/rustc_expand/src/mbe/diagnostics.rs | 13 +++---------- compiler/rustc_expand/src/mbe/macro_parser.rs | 5 ++--- .../array-slice-vec/vec-macro-with-comma-only.rs | 2 +- .../vec-macro-with-comma-only.stderr | 2 +- .../editions/edition-keywords-2015-2015-parsing.rs | 4 ++-- .../edition-keywords-2015-2015-parsing.stderr | 4 ++-- .../editions/edition-keywords-2015-2018-parsing.rs | 4 ++-- .../edition-keywords-2015-2018-parsing.stderr | 4 ++-- .../editions/edition-keywords-2018-2015-parsing.rs | 4 ++-- .../edition-keywords-2018-2015-parsing.stderr | 6 +++--- .../editions/edition-keywords-2018-2018-parsing.rs | 4 ++-- .../edition-keywords-2018-2018-parsing.stderr | 6 +++--- tests/ui/fail-simple.rs | 2 +- tests/ui/fail-simple.stderr | 2 +- .../assert-trailing-junk.with-generic-asset.stderr | 4 ++-- ...sert-trailing-junk.without-generic-asset.stderr | 4 ++-- tests/ui/macros/best-failure.rs | 2 +- tests/ui/macros/best-failure.stderr | 2 +- .../macros/expr_2021_inline_const.edi2021.stderr | 4 ++-- .../macros/expr_2021_inline_const.edi2024.stderr | 2 +- tests/ui/macros/expr_2021_inline_const.rs | 4 ++-- .../expr_2024_underscore_expr.edi2021.stderr | 4 ++-- .../expr_2024_underscore_expr.edi2024.stderr | 2 +- tests/ui/macros/expr_2024_underscore_expr.rs | 4 ++-- tests/ui/macros/macro-at-most-once-rep-2015.rs | 14 +++++++------- tests/ui/macros/macro-at-most-once-rep-2015.stderr | 14 +++++++------- tests/ui/macros/macro-at-most-once-rep-2018.rs | 14 +++++++------- tests/ui/macros/macro-at-most-once-rep-2018.stderr | 14 +++++++------- tests/ui/macros/macro-non-lifetime.rs | 2 +- tests/ui/macros/macro-non-lifetime.stderr | 2 +- tests/ui/macros/missing-comma.rs | 10 +++++----- tests/ui/macros/missing-comma.stderr | 10 +++++----- tests/ui/macros/nonterminal-matching.rs | 10 +++++----- tests/ui/macros/nonterminal-matching.stderr | 14 +++++++------- tests/ui/macros/trace_faulty_macros.stderr | 2 +- tests/ui/offset-of/offset-of-arg-count.rs | 2 +- tests/ui/offset-of/offset-of-arg-count.stderr | 2 +- tests/ui/offset-of/offset-of-tuple.stderr | 2 +- .../or-patterns/or-patterns-syntactic-fail-2018.rs | 4 ++-- .../or-patterns-syntactic-fail-2018.stderr | 4 ++-- tests/ui/parser/macro/macro-doc-comments-1.rs | 2 +- tests/ui/parser/macro/macro-doc-comments-1.stderr | 2 +- tests/ui/parser/macro/macro-doc-comments-2.rs | 2 +- tests/ui/parser/macro/macro-doc-comments-2.stderr | 2 +- .../ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs | 2 +- .../rfcs/rfc-2294-if-let-guard/feature-gate.stderr | 2 +- .../ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs | 2 +- .../rfc-2497-if-let-chains/feature-gate.stderr | 2 +- tests/ui/underscore-ident-matcher.rs | 2 +- tests/ui/underscore-ident-matcher.stderr | 2 +- 50 files changed, 113 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 103bbb05e7ff3..ffcce1e52f67f 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -2,10 +2,9 @@ use std::borrow::Cow; use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage}; use rustc_macros::Subdiagnostic; -use rustc_parse::parser::{Parser, Recovery}; +use rustc_parse::parser::{Parser, Recovery, token_descr}; use rustc_session::parse::ParseSess; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; @@ -336,17 +335,11 @@ pub(super) fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Spa /// other tokens, this is "unexpected token...". pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> { if let Some(expected_token) = expected_token { - Cow::from(format!( - "expected `{}`, found `{}`", - pprust::token_to_string(expected_token), - pprust::token_to_string(tok), - )) + Cow::from(format!("expected {}, found {}", token_descr(expected_token), token_descr(tok))) } else { match tok.kind { token::Eof => Cow::from("unexpected end of macro invocation"), - _ => { - Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))) - } + _ => Cow::from(format!("no rules expected {}", token_descr(tok))), } } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 3903203da3dbf..a54b0a5e0132e 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -78,11 +78,10 @@ use std::rc::Rc; pub(crate) use NamedMatch::*; pub(crate) use ParseResult::*; use rustc_ast::token::{self, DocComment, NonterminalKind, Token}; -use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_lint_defs::pluralize; -use rustc_parse::parser::{ParseNtResult, Parser}; +use rustc_parse::parser::{ParseNtResult, Parser, token_descr}; use rustc_span::Span; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; @@ -150,7 +149,7 @@ impl Display for MatcherLoc { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => { - write!(f, "`{}`", pprust::token_to_string(token)) + write!(f, "{}", token_descr(token)) } MatcherLoc::MetaVarDecl { bind, kind, .. } => { write!(f, "meta-variable `${bind}")?; diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs index 574a53c58feac..0f99f6b1b1e07 100644 --- a/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs +++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs @@ -1,3 +1,3 @@ pub fn main() { - vec![,]; //~ ERROR no rules expected the token `,` + vec![,]; //~ ERROR no rules expected `,` } diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr index b3f953af6d278..d76d493eca839 100644 --- a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr +++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `,` +error: no rules expected `,` --> $DIR/vec-macro-with-comma-only.rs:2:10 | LL | vec![,]; diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs index 07104bdf217d0..4751d280467cb 100644 --- a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs +++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs @@ -13,8 +13,8 @@ pub fn check_async() { let mut r#async = 1; // OK r#async = consumes_async!(async); // OK - r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected `async` r#async = consumes_async_raw!(r#async); // OK if passes_ident!(async) == 1 {} // OK diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr index 39944622d07b9..2519a9fded2ee 100644 --- a/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `r#async` +error: no rules expected `r#async` --> $DIR/edition-keywords-2015-2015-parsing.rs:16:31 | LL | r#async = consumes_async!(r#async); @@ -10,7 +10,7 @@ note: while trying to match `async` LL | (async) => (1) | ^^^^^ -error: no rules expected the token `async` +error: no rules expected `async` --> $DIR/edition-keywords-2015-2015-parsing.rs:17:35 | LL | r#async = consumes_async_raw!(async); diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs index 3c294f95cd265..4404ea26fb30d 100644 --- a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs +++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs @@ -13,8 +13,8 @@ pub fn check_async() { let mut r#async = 1; // OK r#async = consumes_async!(async); // OK - r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected `async` r#async = consumes_async_raw!(r#async); // OK if passes_ident!(async) == 1 {} // OK diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr index fa83908e6666e..0c0e573841519 100644 --- a/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `r#async` +error: no rules expected `r#async` --> $DIR/edition-keywords-2015-2018-parsing.rs:16:31 | LL | r#async = consumes_async!(r#async); @@ -10,7 +10,7 @@ note: while trying to match `async` LL | (async) => (1) | ^^^^^ -error: no rules expected the token `async` +error: no rules expected `async` --> $DIR/edition-keywords-2015-2018-parsing.rs:17:35 | LL | r#async = consumes_async_raw!(async); diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs index 5918454327409..c346be5085601 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -17,8 +17,8 @@ pub fn check_async() { let mut r#async = 1; // OK r#async = consumes_async!(async); // OK - r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected keyword `async` r#async = consumes_async_raw!(r#async); // OK if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr index 42db75f665973..aed5837abeafe 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -20,19 +20,19 @@ help: escape `async` to use it as an identifier LL | module::r#async(); | ++ -error: no rules expected the token `r#async` +error: no rules expected `r#async` --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call | -note: while trying to match `async` +note: while trying to match keyword `async` --> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6 | LL | (async) => (1) | ^^^^^ -error: no rules expected the token `async` +error: no rules expected keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs index 4975246fa9423..b75b68b3febbd 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -24,8 +24,8 @@ pub fn check_async() { let mut r#async = 1; // OK r#async = consumes_async!(async); // OK - r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected keyword `async` r#async = consumes_async_raw!(r#async); // OK if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr index 4bbe1597233cf..6503e9cc73cf1 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -20,19 +20,19 @@ help: escape `async` to use it as an identifier LL | module::r#async(); | ++ -error: no rules expected the token `r#async` +error: no rules expected `r#async` --> $DIR/edition-keywords-2018-2018-parsing.rs:27:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call | -note: while trying to match `async` +note: while trying to match keyword `async` --> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6 | LL | (async) => (1) | ^^^^^ -error: no rules expected the token `async` +error: no rules expected keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:28:35 | LL | r#async = consumes_async_raw!(async); diff --git a/tests/ui/fail-simple.rs b/tests/ui/fail-simple.rs index cd81a5d0a0fc6..55e547ee72b0f 100644 --- a/tests/ui/fail-simple.rs +++ b/tests/ui/fail-simple.rs @@ -1,3 +1,3 @@ fn main() { - panic!(@); //~ ERROR no rules expected the token `@` + panic!(@); //~ ERROR no rules expected `@` } diff --git a/tests/ui/fail-simple.stderr b/tests/ui/fail-simple.stderr index 39fec3e2517b2..50c350b3ef55e 100644 --- a/tests/ui/fail-simple.stderr +++ b/tests/ui/fail-simple.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `@` +error: no rules expected `@` --> $DIR/fail-simple.rs:2:12 | LL | panic!(@); diff --git a/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr index 1e73320e43912..7582c8e8659bc 100644 --- a/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr +++ b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr @@ -10,7 +10,7 @@ error: expected one of `,`, `.`, `?`, or an operator, found `some` LL | assert!(true some extra junk); | ^^^^ expected one of `,`, `.`, `?`, or an operator -error: no rules expected the token `blah` +error: no rules expected `blah` --> $DIR/assert-trailing-junk.rs:15:30 | LL | assert!(true, "whatever" blah); @@ -28,7 +28,7 @@ LL | assert!(true "whatever" blah); | | | help: try adding a comma -error: no rules expected the token `blah` +error: no rules expected `blah` --> $DIR/assert-trailing-junk.rs:18:29 | LL | assert!(true "whatever" blah); diff --git a/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr index 1e73320e43912..7582c8e8659bc 100644 --- a/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr +++ b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr @@ -10,7 +10,7 @@ error: expected one of `,`, `.`, `?`, or an operator, found `some` LL | assert!(true some extra junk); | ^^^^ expected one of `,`, `.`, `?`, or an operator -error: no rules expected the token `blah` +error: no rules expected `blah` --> $DIR/assert-trailing-junk.rs:15:30 | LL | assert!(true, "whatever" blah); @@ -28,7 +28,7 @@ LL | assert!(true "whatever" blah); | | | help: try adding a comma -error: no rules expected the token `blah` +error: no rules expected `blah` --> $DIR/assert-trailing-junk.rs:18:29 | LL | assert!(true "whatever" blah); diff --git a/tests/ui/macros/best-failure.rs b/tests/ui/macros/best-failure.rs index bbdd465d5ec96..1b73066c8749d 100644 --- a/tests/ui/macros/best-failure.rs +++ b/tests/ui/macros/best-failure.rs @@ -2,7 +2,7 @@ macro_rules! number { (neg false, $self:ident) => { $self }; ($signed:tt => $ty:ty;) => { number!(neg $signed, $self); - //~^ ERROR no rules expected the token `$` + //~^ ERROR no rules expected `$` }; } diff --git a/tests/ui/macros/best-failure.stderr b/tests/ui/macros/best-failure.stderr index c5f8b9abc19a1..914ff7fd8207f 100644 --- a/tests/ui/macros/best-failure.stderr +++ b/tests/ui/macros/best-failure.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `$` +error: no rules expected `$` --> $DIR/best-failure.rs:4:30 | LL | macro_rules! number { diff --git a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr index 22d662aaaf2f9..bf7eb3888b33e 100644 --- a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr +++ b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `const` +error: no rules expected keyword `const` --> $DIR/expr_2021_inline_const.rs:23:12 | LL | macro_rules! m2021 { @@ -13,7 +13,7 @@ note: while trying to match meta-variable `$e:expr_2021` LL | ($e:expr_2021) => { | ^^^^^^^^^^^^ -error: no rules expected the token `const` +error: no rules expected keyword `const` --> $DIR/expr_2021_inline_const.rs:24:12 | LL | macro_rules! m2024 { diff --git a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr index 2555e4f757a52..1028ddc4267fc 100644 --- a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr +++ b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `const` +error: no rules expected keyword `const` --> $DIR/expr_2021_inline_const.rs:23:12 | LL | macro_rules! m2021 { diff --git a/tests/ui/macros/expr_2021_inline_const.rs b/tests/ui/macros/expr_2021_inline_const.rs index 39a542fe4d94a..312256f1879c3 100644 --- a/tests/ui/macros/expr_2021_inline_const.rs +++ b/tests/ui/macros/expr_2021_inline_const.rs @@ -20,8 +20,8 @@ macro_rules! test { } fn main() { - m2021!(const { 1 }); //~ ERROR: no rules expected the token `const` - m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected the token `const` + m2021!(const { 1 }); //~ ERROR: no rules expected keyword `const` + m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected keyword `const` test!(expr); } diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr index 34df20a69ef51..7b3ca54bb7132 100644 --- a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr +++ b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `_` +error: no rules expected reserved identifier `_` --> $DIR/expr_2024_underscore_expr.rs:19:12 | LL | macro_rules! m2021 { @@ -13,7 +13,7 @@ note: while trying to match meta-variable `$e:expr_2021` LL | ($e:expr_2021) => { | ^^^^^^^^^^^^ -error: no rules expected the token `_` +error: no rules expected reserved identifier `_` --> $DIR/expr_2024_underscore_expr.rs:20:12 | LL | macro_rules! m2024 { diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr index 372c5d8637c9f..59104dafa1816 100644 --- a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr +++ b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `_` +error: no rules expected reserved identifier `_` --> $DIR/expr_2024_underscore_expr.rs:19:12 | LL | macro_rules! m2021 { diff --git a/tests/ui/macros/expr_2024_underscore_expr.rs b/tests/ui/macros/expr_2024_underscore_expr.rs index 86e3137450685..6f8ec139109bb 100644 --- a/tests/ui/macros/expr_2024_underscore_expr.rs +++ b/tests/ui/macros/expr_2024_underscore_expr.rs @@ -16,6 +16,6 @@ macro_rules! m2024 { } fn main() { - m2021!(_); //~ ERROR: no rules expected the token `_` - m2024!(_); //[edi2021]~ ERROR: no rules expected the token `_` + m2021!(_); //~ ERROR: no rules expected reserved identifier `_` + m2024!(_); //[edi2021]~ ERROR: no rules expected reserved identifier `_` } diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.rs b/tests/ui/macros/macro-at-most-once-rep-2015.rs index 8f2531a25aeaf..08967b82531c9 100644 --- a/tests/ui/macros/macro-at-most-once-rep-2015.rs +++ b/tests/ui/macros/macro-at-most-once-rep-2015.rs @@ -22,21 +22,21 @@ macro_rules! barstar { pub fn main() { foo!(); foo!(a); - foo!(a?); //~ ERROR no rules expected the token `?` - foo!(a?a); //~ ERROR no rules expected the token `?` - foo!(a?a?a); //~ ERROR no rules expected the token `?` + foo!(a?); //~ ERROR no rules expected `?` + foo!(a?a); //~ ERROR no rules expected `?` + foo!(a?a?a); //~ ERROR no rules expected `?` barplus!(); //~ERROR unexpected end of macro invocation barplus!(a); //~ERROR unexpected end of macro invocation - barplus!(a?); //~ ERROR no rules expected the token `?` - barplus!(a?a); //~ ERROR no rules expected the token `?` + barplus!(a?); //~ ERROR no rules expected `?` + barplus!(a?a); //~ ERROR no rules expected `?` barplus!(a+); barplus!(+); barstar!(); //~ERROR unexpected end of macro invocation barstar!(a); //~ERROR unexpected end of macro invocation - barstar!(a?); //~ ERROR no rules expected the token `?` - barstar!(a?a); //~ ERROR no rules expected the token `?` + barstar!(a?); //~ ERROR no rules expected `?` + barstar!(a?a); //~ ERROR no rules expected `?` barstar!(a*); barstar!(*); } diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.stderr b/tests/ui/macros/macro-at-most-once-rep-2015.stderr index 7c45b85bc8d4e..7f161cdc8d0b4 100644 --- a/tests/ui/macros/macro-at-most-once-rep-2015.stderr +++ b/tests/ui/macros/macro-at-most-once-rep-2015.stderr @@ -4,7 +4,7 @@ error: the `?` macro repetition operator does not take a separator LL | ($(a),?) => {}; | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:25:11 | LL | macro_rules! foo { @@ -15,7 +15,7 @@ LL | foo!(a?); | = note: while trying to match sequence end -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:26:11 | LL | macro_rules! foo { @@ -26,7 +26,7 @@ LL | foo!(a?a); | = note: while trying to match sequence end -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:27:11 | LL | macro_rules! foo { @@ -67,7 +67,7 @@ note: while trying to match `+` LL | ($(a)?+) => {}; // ok. matches "a+" and "+" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:31:15 | LL | macro_rules! barplus { @@ -82,7 +82,7 @@ note: while trying to match `+` LL | ($(a)?+) => {}; // ok. matches "a+" and "+" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:32:15 | LL | macro_rules! barplus { @@ -127,7 +127,7 @@ note: while trying to match `*` LL | ($(a)?*) => {}; // ok. matches "a*" and "*" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:38:15 | LL | macro_rules! barstar { @@ -142,7 +142,7 @@ note: while trying to match `*` LL | ($(a)?*) => {}; // ok. matches "a*" and "*" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2015.rs:39:15 | LL | macro_rules! barstar { diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.rs b/tests/ui/macros/macro-at-most-once-rep-2018.rs index 7f43055ded6f4..98fbb2ad20733 100644 --- a/tests/ui/macros/macro-at-most-once-rep-2018.rs +++ b/tests/ui/macros/macro-at-most-once-rep-2018.rs @@ -22,21 +22,21 @@ macro_rules! barstar { pub fn main() { foo!(); foo!(a); - foo!(a?); //~ ERROR no rules expected the token `?` - foo!(a?a); //~ ERROR no rules expected the token `?` - foo!(a?a?a); //~ ERROR no rules expected the token `?` + foo!(a?); //~ ERROR no rules expected `?` + foo!(a?a); //~ ERROR no rules expected `?` + foo!(a?a?a); //~ ERROR no rules expected `?` barplus!(); //~ERROR unexpected end of macro invocation barplus!(a); //~ERROR unexpected end of macro invocation - barplus!(a?); //~ ERROR no rules expected the token `?` - barplus!(a?a); //~ ERROR no rules expected the token `?` + barplus!(a?); //~ ERROR no rules expected `?` + barplus!(a?a); //~ ERROR no rules expected `?` barplus!(a+); barplus!(+); barstar!(); //~ERROR unexpected end of macro invocation barstar!(a); //~ERROR unexpected end of macro invocation - barstar!(a?); //~ ERROR no rules expected the token `?` - barstar!(a?a); //~ ERROR no rules expected the token `?` + barstar!(a?); //~ ERROR no rules expected `?` + barstar!(a?a); //~ ERROR no rules expected `?` barstar!(a*); barstar!(*); } diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.stderr b/tests/ui/macros/macro-at-most-once-rep-2018.stderr index 696520b28268a..f165a199b10b9 100644 --- a/tests/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/tests/ui/macros/macro-at-most-once-rep-2018.stderr @@ -4,7 +4,7 @@ error: the `?` macro repetition operator does not take a separator LL | ($(a),?) => {}; | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:25:11 | LL | macro_rules! foo { @@ -15,7 +15,7 @@ LL | foo!(a?); | = note: while trying to match sequence end -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:26:11 | LL | macro_rules! foo { @@ -26,7 +26,7 @@ LL | foo!(a?a); | = note: while trying to match sequence end -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:27:11 | LL | macro_rules! foo { @@ -67,7 +67,7 @@ note: while trying to match `+` LL | ($(a)?+) => {}; // ok. matches "a+" and "+" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:31:15 | LL | macro_rules! barplus { @@ -82,7 +82,7 @@ note: while trying to match `+` LL | ($(a)?+) => {}; // ok. matches "a+" and "+" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:32:15 | LL | macro_rules! barplus { @@ -127,7 +127,7 @@ note: while trying to match `*` LL | ($(a)?*) => {}; // ok. matches "a*" and "*" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:38:15 | LL | macro_rules! barstar { @@ -142,7 +142,7 @@ note: while trying to match `*` LL | ($(a)?*) => {}; // ok. matches "a*" and "*" | ^ -error: no rules expected the token `?` +error: no rules expected `?` --> $DIR/macro-at-most-once-rep-2018.rs:39:15 | LL | macro_rules! barstar { diff --git a/tests/ui/macros/macro-non-lifetime.rs b/tests/ui/macros/macro-non-lifetime.rs index 26e1f2afa91bb..3defffd29604a 100644 --- a/tests/ui/macros/macro-non-lifetime.rs +++ b/tests/ui/macros/macro-non-lifetime.rs @@ -4,5 +4,5 @@ macro_rules! m { ($x:lifetime) => { } } fn main() { m!(a); - //~^ ERROR no rules expected the token `a` + //~^ ERROR no rules expected `a` } diff --git a/tests/ui/macros/macro-non-lifetime.stderr b/tests/ui/macros/macro-non-lifetime.stderr index 9ff3d741c01d2..35040a2229bd3 100644 --- a/tests/ui/macros/macro-non-lifetime.stderr +++ b/tests/ui/macros/macro-non-lifetime.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `a` +error: no rules expected `a` --> $DIR/macro-non-lifetime.rs:6:8 | LL | macro_rules! m { ($x:lifetime) => { } } diff --git a/tests/ui/macros/missing-comma.rs b/tests/ui/macros/missing-comma.rs index 92f8a77950583..64cfb0db31a0b 100644 --- a/tests/ui/macros/missing-comma.rs +++ b/tests/ui/macros/missing-comma.rs @@ -19,16 +19,16 @@ fn main() { println!("{}" a); //~^ ERROR expected `,`, found `a` foo!(a b); - //~^ ERROR no rules expected the token `b` + //~^ ERROR no rules expected `b` foo!(a, b, c, d e); - //~^ ERROR no rules expected the token `e` + //~^ ERROR no rules expected `e` foo!(a, b, c d, e); - //~^ ERROR no rules expected the token `d` + //~^ ERROR no rules expected `d` foo!(a, b, c d e); - //~^ ERROR no rules expected the token `d` + //~^ ERROR no rules expected `d` bar!(Level::Error, ); //~^ ERROR unexpected end of macro invocation check!(::fmt, "fmt"); check!(::fmt, "fmt",); - //~^ ERROR no rules expected the token `,` + //~^ ERROR no rules expected `,` } diff --git a/tests/ui/macros/missing-comma.stderr b/tests/ui/macros/missing-comma.stderr index 81877a29ed8ae..9913ba3491927 100644 --- a/tests/ui/macros/missing-comma.stderr +++ b/tests/ui/macros/missing-comma.stderr @@ -4,7 +4,7 @@ error: expected `,`, found `a` LL | println!("{}" a); | ^ expected `,` -error: no rules expected the token `b` +error: no rules expected `b` --> $DIR/missing-comma.rs:21:12 | LL | macro_rules! foo { @@ -21,7 +21,7 @@ note: while trying to match meta-variable `$a:ident` LL | ($a:ident) => (); | ^^^^^^^^ -error: no rules expected the token `e` +error: no rules expected `e` --> $DIR/missing-comma.rs:23:21 | LL | macro_rules! foo { @@ -38,7 +38,7 @@ note: while trying to match meta-variable `$d:ident` LL | ($a:ident, $b:ident, $c:ident, $d:ident) => (); | ^^^^^^^^ -error: no rules expected the token `d` +error: no rules expected `d` --> $DIR/missing-comma.rs:25:18 | LL | macro_rules! foo { @@ -55,7 +55,7 @@ note: while trying to match meta-variable `$c:ident` LL | ($a:ident, $b:ident, $c:ident) => (); | ^^^^^^^^ -error: no rules expected the token `d` +error: no rules expected `d` --> $DIR/missing-comma.rs:27:18 | LL | macro_rules! foo { @@ -85,7 +85,7 @@ note: while trying to match meta-variable `$arg:tt` LL | ($lvl:expr, $($arg:tt)+) => {} | ^^^^^^^ -error: no rules expected the token `,` +error: no rules expected `,` --> $DIR/missing-comma.rs:32:38 | LL | macro_rules! check { diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index 5f0d6b2f90eee..a655b66510311 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -16,7 +16,7 @@ macro complex_nonterminal($nt_item: item) { struct S; } - n!(a $nt_item b); //~ ERROR no rules expected the token `enum E {}` + n!(a $nt_item b); //~ ERROR no rules expected item `enum E {}` } simple_nonterminal!(a, 'a, (x, y, z)); // OK @@ -29,10 +29,10 @@ macro_rules! foo { (ident $x:ident) => { bar!(ident $x); }; (lifetime $x:lifetime) => { bar!(lifetime $x); }; (tt $x:tt) => { bar!(tt $x); }; - (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected the token `3` - (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected the token `4` - (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected the token `a::b::c` - (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected the token `let abc = 0` + (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` + (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` + (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected path `a::b::c` + (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected statement `let abc = 0` } macro_rules! bar { diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index 3ee88b5f52ef9..e283dfcb8fdc4 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `enum E {}` +error: no rules expected item `enum E {}` --> $DIR/nonterminal-matching.rs:19:10 | LL | macro n(a $nt_item b) { @@ -10,7 +10,7 @@ LL | n!(a $nt_item b); LL | complex_nonterminal!(enum E {}); | ------------------------------- in this macro invocation | -note: while trying to match `enum E {}` +note: while trying to match item `enum E {}` --> $DIR/nonterminal-matching.rs:15:15 | LL | macro n(a $nt_item b) { @@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected the token `3` +error: no rules expected expression `3` --> $DIR/nonterminal-matching.rs:32:35 | LL | (expr $x:expr) => { bar!(expr $x); }; @@ -45,7 +45,7 @@ LL | (expr 3) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected the token `4` +error: no rules expected literal `4` --> $DIR/nonterminal-matching.rs:33:44 | LL | (literal $x:literal) => { bar!(literal $x); }; @@ -67,7 +67,7 @@ LL | (literal 4) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected the token `a::b::c` +error: no rules expected path `a::b::c` --> $DIR/nonterminal-matching.rs:34:35 | LL | (path $x:path) => { bar!(path $x); }; @@ -89,7 +89,7 @@ LL | (path a::b::c) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected the token `let abc = 0` +error: no rules expected statement `let abc = 0` --> $DIR/nonterminal-matching.rs:35:35 | LL | (stmt $x:stmt) => { bar!(stmt $x); }; @@ -101,7 +101,7 @@ LL | macro_rules! bar { LL | foo!(stmt let abc = 0); | ---------------------- in this macro invocation | -note: while trying to match `let` +note: while trying to match keyword `let` --> $DIR/nonterminal-matching.rs:45:11 | LL | (stmt let abc = 0) => {}; diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index 66d7b76bb0726..10ad3faab1612 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `bcd` +error: no rules expected `bcd` --> $DIR/trace_faulty_macros.rs:7:26 | LL | macro_rules! my_faulty_macro { diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs index c86e61a61a725..f4c8b91d7daee 100644 --- a/tests/ui/offset-of/offset-of-arg-count.rs +++ b/tests/ui/offset-of/offset-of-arg-count.rs @@ -3,7 +3,7 @@ use std::mem::offset_of; fn main() { offset_of!(NotEnoughArguments); //~ ERROR unexpected end of macro invocation offset_of!(NotEnoughArgumentsWithAComma, ); //~ ERROR unexpected end of macro invocation - offset_of!(Container, field, too many arguments); //~ ERROR no rules expected the token `too` + offset_of!(Container, field, too many arguments); //~ ERROR no rules expected `too` offset_of!(S, f); // compiles fine offset_of!(S, f,); // also compiles fine offset_of!(S, f.); //~ ERROR unexpected token: `)` diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr index 4cb24b3d034b6..0772bb18e0c62 100644 --- a/tests/ui/offset-of/offset-of-arg-count.stderr +++ b/tests/ui/offset-of/offset-of-arg-count.stderr @@ -16,7 +16,7 @@ LL | offset_of!(NotEnoughArgumentsWithAComma, ); note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -error: no rules expected the token `too` +error: no rules expected `too` --> $DIR/offset-of-arg-count.rs:6:34 | LL | offset_of!(Container, field, too many arguments); diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index dd20859e04e1b..38ce49c9179ba 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -76,7 +76,7 @@ error: suffixes on a tuple index are invalid LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` -error: no rules expected the token `+` +error: no rules expected `+` --> $DIR/offset-of-tuple.rs:11:26 | LL | offset_of!((u8, u8), +1); diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs index 7a94c96b79d89..fb227bf0e915f 100644 --- a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs @@ -9,5 +9,5 @@ macro_rules! accept_pat { ($p:pat) => {}; } -accept_pat!(p | q); //~ ERROR no rules expected the token `|` -accept_pat!(|p| q); //~ ERROR no rules expected the token `|` +accept_pat!(p | q); //~ ERROR no rules expected `|` +accept_pat!(|p| q); //~ ERROR no rules expected `|` diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr index acc2099bbc6a8..47dac84ee4947 100644 --- a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `|` +error: no rules expected `|` --> $DIR/or-patterns-syntactic-fail-2018.rs:12:15 | LL | macro_rules! accept_pat { @@ -13,7 +13,7 @@ note: while trying to match meta-variable `$p:pat` LL | ($p:pat) => {}; | ^^^^^^ -error: no rules expected the token `|` +error: no rules expected `|` --> $DIR/or-patterns-syntactic-fail-2018.rs:13:13 | LL | macro_rules! accept_pat { diff --git a/tests/ui/parser/macro/macro-doc-comments-1.rs b/tests/ui/parser/macro/macro-doc-comments-1.rs index 8d8103bb1e065..1aaa993e0721d 100644 --- a/tests/ui/parser/macro/macro-doc-comments-1.rs +++ b/tests/ui/parser/macro/macro-doc-comments-1.rs @@ -4,6 +4,6 @@ macro_rules! outer { outer! { //! Inner -} //~^ ERROR no rules expected the token `!` +} //~^ ERROR no rules expected `!` fn main() { } diff --git a/tests/ui/parser/macro/macro-doc-comments-1.stderr b/tests/ui/parser/macro/macro-doc-comments-1.stderr index 9d2d1bc00725a..6b7e758980c2b 100644 --- a/tests/ui/parser/macro/macro-doc-comments-1.stderr +++ b/tests/ui/parser/macro/macro-doc-comments-1.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `!` +error: no rules expected `!` --> $DIR/macro-doc-comments-1.rs:6:5 | LL | macro_rules! outer { diff --git a/tests/ui/parser/macro/macro-doc-comments-2.rs b/tests/ui/parser/macro/macro-doc-comments-2.rs index 8f33720ae80eb..2bee2435ef872 100644 --- a/tests/ui/parser/macro/macro-doc-comments-2.rs +++ b/tests/ui/parser/macro/macro-doc-comments-2.rs @@ -4,6 +4,6 @@ macro_rules! inner { inner! { /// Outer -} //~^ ERROR no rules expected the token `[` +} //~^ ERROR no rules expected `[` fn main() { } diff --git a/tests/ui/parser/macro/macro-doc-comments-2.stderr b/tests/ui/parser/macro/macro-doc-comments-2.stderr index 22efd995b463c..02c12bf959114 100644 --- a/tests/ui/parser/macro/macro-doc-comments-2.stderr +++ b/tests/ui/parser/macro/macro-doc-comments-2.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `[` +error: no rules expected `[` --> $DIR/macro-doc-comments-2.rs:6:5 | LL | macro_rules! inner { diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs index b8c0eb3e6d6d7..4b2fc4a03b620 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs @@ -68,7 +68,7 @@ fn _macros() { _ => {} } use_expr!(let 0 = 1); - //~^ ERROR no rules expected the token `let` + //~^ ERROR no rules expected keyword `let` } fn main() {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr index 2341dbbbdbd00..1c710b04897cb 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr @@ -131,7 +131,7 @@ LL | use_expr!((let 0 = 1)); | = note: only supported directly in conditions of `if` and `while` expressions -error: no rules expected the token `let` +error: no rules expected keyword `let` --> $DIR/feature-gate.rs:70:15 | LL | macro_rules! use_expr { diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs index bca7564efd83f..2087fc42cf102 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs @@ -54,7 +54,7 @@ fn _macros() { #[cfg(FALSE)] (let 0 = 1); //~^ ERROR expected expression, found `let` statement use_expr!(let 0 = 1); - //~^ ERROR no rules expected the token `let` + //~^ ERROR no rules expected keyword `let` } fn main() {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr index 2b1a49be3daa5..7c874ae78a8ad 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr @@ -14,7 +14,7 @@ LL | noop_expr!((let 0 = 1)); | = note: only supported directly in conditions of `if` and `while` expressions -error: no rules expected the token `let` +error: no rules expected keyword `let` --> $DIR/feature-gate.rs:56:15 | LL | macro_rules! use_expr { diff --git a/tests/ui/underscore-ident-matcher.rs b/tests/ui/underscore-ident-matcher.rs index bddc8c80a7b96..77ec70d43d54e 100644 --- a/tests/ui/underscore-ident-matcher.rs +++ b/tests/ui/underscore-ident-matcher.rs @@ -5,5 +5,5 @@ macro_rules! identity { } fn main() { - let identity!(_) = 10; //~ ERROR no rules expected the token `_` + let identity!(_) = 10; //~ ERROR no rules expected reserved identifier `_` } diff --git a/tests/ui/underscore-ident-matcher.stderr b/tests/ui/underscore-ident-matcher.stderr index a663f34cde1b1..0c3f980cf6c71 100644 --- a/tests/ui/underscore-ident-matcher.stderr +++ b/tests/ui/underscore-ident-matcher.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `_` +error: no rules expected reserved identifier `_` --> $DIR/underscore-ident-matcher.rs:8:19 | LL | macro_rules! identity { From 826e0ca885f5c1747172e96cda5493f6344f9425 Mon Sep 17 00:00:00 2001 From: David Tenty Date: Tue, 29 Oct 2024 10:00:40 -0400 Subject: [PATCH 03/13] powerpc64-ibm-aix: update maintainters Chaofan and Kai will be passing over maintainership for the target over to David Tenty and Chris Cambly. --- src/doc/rustc/src/platform-support/aix.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md index c3ce71a183568..5a198062b9529 100644 --- a/src/doc/rustc/src/platform-support/aix.md +++ b/src/doc/rustc/src/platform-support/aix.md @@ -6,8 +6,8 @@ Rust for AIX operating system, currently only 64-bit PowerPC is supported. ## Target maintainers -- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises -- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq +- David Tenty `daltenty@ibm.com`, https://github.com/daltenty +- Chris Cambly, `ccambly@ca.ibm.com`, https://github.com/gilamn5tr ## Requirements From f51ec110a714fea09105586b26c7f8e6a2a57018 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 18 Oct 2024 00:28:43 +0200 Subject: [PATCH 04/13] TypingMode :thinking: --- compiler/rustc_borrowck/src/lib.rs | 4 +- .../src/region_infer/opaque_types.rs | 14 +-- compiler/rustc_codegen_ssa/src/base.rs | 4 +- .../src/check_consts/check.rs | 4 +- .../rustc_const_eval/src/check_consts/ops.rs | 4 +- .../src/check_consts/qualifs.rs | 10 +- .../src/interpret/eval_context.rs | 6 +- .../src/util/compare_types.rs | 5 +- .../rustc_hir_analysis/src/check/check.rs | 8 +- .../src/check/compare_impl_item.rs | 14 +-- .../src/check/compare_impl_item/refine.rs | 4 +- .../rustc_hir_analysis/src/check/dropck.rs | 4 +- .../rustc_hir_analysis/src/check/entry.rs | 4 +- compiler/rustc_hir_analysis/src/check/mod.rs | 6 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 +- .../src/coherence/builtin.rs | 8 +- .../src/coherence/orphan.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 10 +- .../src/hir_ty_lowering/mod.rs | 6 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 4 +- .../src/impl_wf_check/min_specialization.rs | 8 +- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 5 +- compiler/rustc_infer/src/infer/at.rs | 36 +++++-- .../src/infer/canonical/canonicalizer.rs | 6 +- compiler/rustc_infer/src/infer/context.rs | 17 ++-- compiler/rustc_infer/src/infer/mod.rs | 99 +++++++------------ .../rustc_infer/src/infer/opaque_types/mod.rs | 49 ++++----- .../src/infer/relate/generalize.rs | 11 ++- compiler/rustc_lint/src/builtin.rs | 8 +- compiler/rustc_lint/src/context.rs | 12 ++- .../src/for_loops_over_fallibles.rs | 2 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 4 +- compiler/rustc_lint/src/non_fmt_panic.rs | 2 +- .../src/opaque_hidden_inferred_bound.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 18 ++-- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_mir_build/src/build/mod.rs | 10 +- .../src/thir/pattern/const_to_pat.rs | 6 +- compiler/rustc_mir_transform/src/coroutine.rs | 8 +- compiler/rustc_mir_transform/src/validate.rs | 4 +- .../rustc_next_trait_solver/src/delegate.rs | 4 +- .../src/solve/assembly/mod.rs | 14 ++- .../src/solve/eval_ctxt/canonical.rs | 3 +- .../src/solve/eval_ctxt/mod.rs | 23 ++--- .../src/solve/normalizes_to/mod.rs | 17 ++-- .../src/solve/normalizes_to/opaque_types.rs | 50 +++++----- .../src/solve/trait_goals.rs | 49 +++++---- compiler/rustc_passes/src/check_attr.rs | 4 +- compiler/rustc_passes/src/layout_test.rs | 3 +- .../src/solve/delegate.rs | 24 ++--- .../src/traits/auto_trait.rs | 5 +- .../src/traits/coherence.rs | 16 +-- .../src/traits/dyn_compatibility.rs | 4 +- .../src/traits/fulfill.rs | 17 ++-- .../rustc_trait_selection/src/traits/misc.rs | 6 +- .../rustc_trait_selection/src/traits/mod.rs | 18 ++-- .../src/traits/project.rs | 36 ++----- .../src/traits/query/evaluate_obligation.rs | 1 - .../src/traits/select/candidate_assembly.rs | 11 ++- .../src/traits/select/mod.rs | 93 ++++++----------- .../src/traits/specialize/mod.rs | 6 +- .../src/traits/vtable.rs | 5 +- compiler/rustc_traits/src/codegen.rs | 4 +- .../src/normalize_erasing_regions.rs | 4 +- compiler/rustc_ty_utils/src/common_traits.rs | 4 +- compiler/rustc_ty_utils/src/instance.rs | 4 +- .../rustc_ty_utils/src/structural_match.rs | 4 +- compiler/rustc_type_ir/src/canonical.rs | 4 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 68 ++++++++++++- compiler/rustc_type_ir/src/interner.rs | 23 ++--- compiler/rustc_type_ir/src/relate/combine.rs | 18 ++-- .../rustc_type_ir/src/search_graph/mod.rs | 21 +--- compiler/rustc_type_ir/src/solve/mod.rs | 13 --- 75 files changed, 512 insertions(+), 505 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 698fdafc93616..742d68ad076e4 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -34,7 +34,7 @@ use rustc_infer::infer::{ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ @@ -440,7 +440,7 @@ pub struct BorrowckInferCtxt<'tcx> { impl<'tcx> BorrowckInferCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { - let infcx = tcx.infer_ctxt().with_opaque_type_inference(def_id).build(); + let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id)); BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) } } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index abce98265b3cb..741dac9e7639d 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -9,6 +9,7 @@ use rustc_macros::extension; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, + TypingMode, }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -340,14 +341,13 @@ fn check_opaque_type_well_formed<'tcx>( parent_def_id = tcx.local_parent(parent_def_id); } - // FIXME(-Znext-solver): We probably should use `&[]` instead of - // and prepopulate this `InferCtxt` with known opaque values, rather than - // allowing opaque types to be defined and checking them after the fact. + // FIXME(#132279): This should eventually use the already defined hidden types + // instead. Alternatively we'll entirely remove this function given we also check + // the opaque in `check_opaque_meets_bounds` later. let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(parent_def_id) - .build(); + .build(TypingMode::analysis_in_body(tcx, parent_def_id)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let identity_args = GenericArgs::identity_for_item(tcx, def_id); @@ -517,7 +517,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { }, ); - let infcx = tcx.infer_ctxt().build(); + // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're + // in a body here. + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new(&infcx); let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b954633f4532d..cb4c9c078b197 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -21,7 +21,7 @@ use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; @@ -119,7 +119,7 @@ pub fn validate_trivial_unsize<'tcx>( ) -> bool { match (source_data.principal(), target_data.principal()) { (Some(hr_source_principal), Some(hr_target_principal)) => { - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); infcx.enter_forall(hr_target_principal, |target_principal| { diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 004fb12419f11..0880b924d3802 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt, TypingMode}; use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; @@ -593,7 +593,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish // which path expressions are getting called on and which path expressions are only used // as function pointers. This is required for correctness. - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args); diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 3ac06ae64910c..3f977dc4b05aa 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::CallSource; use rustc_middle::span_bug; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ - self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, + self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, TypingMode, suggest_constraining_type_param, }; use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind}; @@ -116,7 +116,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let mut selcx = SelectionContext::new(&infcx); let implsrc = selcx.select(&obligation); diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 547030a185435..e8637ba45cf1d 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -114,11 +114,11 @@ impl Qualif for HasMutInterior { ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ); - let infcx = cx - .tcx - .infer_ctxt() - .with_opaque_type_inference(cx.body.source.def_id().expect_local()) - .build(); + // FIXME(#132279): This should eventually use the already defined hidden types. + let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body( + cx.tcx, + cx.body.source.def_id().expect_local(), + )); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a1c773a4b8005..d81368e9fcc39 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -9,7 +9,9 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance}; +use rustc_middle::ty::{ + self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance, +}; use rustc_middle::{mir, span_bug}; use rustc_session::Limit; use rustc_span::Span; @@ -325,7 +327,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let infcx = self.tcx.infer_ctxt().build(); + let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env)); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index 3ea54146fc787..7af977bab4d66 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance}; +use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance}; use rustc_trait_selection::traits::ObligationCtxt; /// Returns whether the two types are equal up to subtyping. @@ -45,7 +45,8 @@ pub fn relate_types<'tcx>( } let mut builder = tcx.infer_ctxt().ignoring_regions(); - let infcx = builder.build(); + // FIXME(#132279): This should eventually use the already defined hidden types. + let infcx = builder.build(TypingMode::from_param_env(param_env)); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 6d04bdf7e48ed..f830108a02f4f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -30,6 +30,7 @@ use rustc_trait_selection::traits; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_type_ir::fold::TypeFoldable; use tracing::{debug, instrument}; +use ty::TypingMode; use {rustc_attr as attr, rustc_hir as hir}; use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty}; @@ -276,7 +277,8 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build(); + // FIXME(#132279): This should eventually use the already defined hidden types. + let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let args = match *origin { @@ -1675,8 +1677,8 @@ pub(super) fn check_coroutine_obligations( // typeck writeback gives us predicates with their regions erased. // As borrowck already has checked lifetimes, we do not need to do it again. .ignoring_regions() - .with_opaque_type_inference(def_id) - .build(); + // FIXME(#132279): This should eventually use the already defined hidden types. + .build(TypingMode::analysis_in_body(tcx, def_id)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for (predicate, cause) in &typeck_results.coroutine_stalled_predicates { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9de96b7ba7760..db2c44fd29df4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::{ self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, Upcast, + TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::Span; @@ -228,7 +228,7 @@ fn compare_method_predicate_entailment<'tcx>( let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); debug!(caller_bounds=?param_env.caller_bounds()); - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); // Create obligations for each predicate declared by the impl @@ -516,7 +516,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id), ); - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); // Normalize the impl signature with fresh variables for lifetime inference. @@ -1196,7 +1196,7 @@ fn compare_self_type<'tcx>( let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); let param_env = ty::ParamEnv::reveal_all(); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { @@ -1801,7 +1801,7 @@ fn compare_const_predicate_entailment<'tcx>( ObligationCause::misc(impl_ct_span, impl_ct_def_id), ); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity(); @@ -1951,7 +1951,7 @@ fn compare_type_predicate_entailment<'tcx>( let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); debug!(caller_bounds=?param_env.caller_bounds()); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for (predicate, span) in impl_ty_own_bounds { @@ -2036,7 +2036,7 @@ pub(super) fn check_type_bounds<'tcx>( let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id); let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); // A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 2d6b9813271e2..646c104f1f553 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -8,7 +8,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, + TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_span::Span; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -132,7 +132,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy()); - let ref infcx = tcx.infer_ctxt().build(); + let ref infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new(infcx); // Normalize the bounds. This has two purposes: diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 97a29b32c0158..1c9bbe627fb07 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -9,7 +9,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode}; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -124,7 +124,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( adt_def_id: LocalDefId, adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_span = tcx.def_span(drop_impl_def_id.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 7da2cd93d4e01..0beb1f98d56de 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::span_bug; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_session::config::EntryFnType; use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; @@ -128,7 +128,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span }); return; }; - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = traits::ObligationCause::new( return_ty_span, main_diagnostics_def_id, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index ec5a89ec9d914..e9eea36a0e66c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -85,7 +85,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; use rustc_span::def_id::CRATE_DEF_ID; @@ -530,7 +530,7 @@ fn suggestion_signature<'tcx>( let ty = tcx.type_of(assoc.def_id).instantiate_identity(); let val = tcx .infer_ctxt() - .build() + .build(TypingMode::non_body_analysis()) .err_ctxt() .ty_kind_suggestion(tcx.param_env(assoc.def_id), ty) .unwrap_or_else(|| "value".to_string()); @@ -620,7 +620,7 @@ pub fn check_function_signature<'tcx>( let param_env = ty::ParamEnv::empty(); - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); let actual_sig = tcx.fn_sig(fn_id).instantiate_identity(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 499e42d31c97f..12ed7b89f68be 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; @@ -106,7 +106,7 @@ where F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>, { let param_env = tcx.param_env(body_def_id); - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env }; @@ -765,7 +765,7 @@ fn test_region_obligations<'tcx>( // Unfortunately, we have to use a new `InferCtxt` each call, because // region constraints get added and solved there and we need to test each // call individually. - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); add_constraints(&infcx); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b4f6b5a9dd24f..5ff52376837eb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -15,7 +15,9 @@ use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_params}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params, +}; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::misc::{ @@ -213,7 +215,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() let param_env = tcx.param_env(impl_did); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = ObligationCause::misc(span, impl_did); // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw @@ -354,7 +356,7 @@ pub(crate) fn coerce_unsized_info<'tcx>( debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = ObligationCause::misc(span, impl_did); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 04770469132bb..8a1a887766c75 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -7,7 +7,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -302,7 +302,7 @@ fn orphan_check<'tcx>( } // (1) Instantiate all generic params with fresh inference vars. - let infcx = tcx.infer_ctxt().intercrate(true).build(); + let infcx = tcx.infer_ctxt().build(TypingMode::Coherence); let cause = traits::ObligationCause::dummy(); let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id()); let trait_ref = trait_ref.instantiate(tcx, args); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 3add801cf5649..cca52c5142c61 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, Span}; @@ -1438,9 +1438,11 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); recovered_ret_ty = Some(suggestable_ret_ty); - } else if let Some(sugg) = - suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty) - { + } else if let Some(sugg) = suggest_impl_trait( + &tcx.infer_ctxt().build(TypingMode::non_body_analysis()), + tcx.param_env(def_id), + ret_ty, + ) { diag.span_suggestion( ty.span, "replace with an appropriate return type", diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 0891642f2c88c..2d0c3ec28c372 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -39,7 +39,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, - TypeVisitableExt, + TypeVisitableExt, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; @@ -1300,7 +1300,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(infcx) => infcx, None => { assert!(!self_ty.has_infer()); - infcx_ = tcx.infer_ctxt().ignoring_regions().build(); + infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); &infcx_ } }; @@ -1492,7 +1492,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { infcx } else { assert!(!qself_ty.has_infer()); - infcx_ = tcx.infer_ctxt().build(); + infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); &infcx_ }; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 2fa4ca680737d..5b0165bf993da 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::debug; @@ -68,7 +68,7 @@ fn diagnostic_hir_wf_check<'tcx>( impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - let infcx = self.tcx.infer_ctxt().build(); + let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let tcx_ty = self.icx.lower_ty(ty); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index a394fc2fbb199..b0c9aed5d8557 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -72,7 +72,9 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::trait_def::TraitSpecializationKind; -use rustc_middle::ty::{self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt, TypingMode, +}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; @@ -195,7 +197,7 @@ fn get_impl_args( impl1_def_id: LocalDefId, impl2_node: Node, ) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> { - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); let param_env = tcx.param_env(impl1_def_id); let impl1_span = tcx.def_span(impl1_def_id); @@ -409,7 +411,7 @@ fn check_predicates<'tcx>( // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args { - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let obligations = wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span) .unwrap(); diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 18e40cfa42874..903be7e732afa 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -8,7 +8,7 @@ use rustc_hir::{HirId, HirIdMap}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::span_bug; use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_span::Span; use rustc_span::def_id::LocalDefIdMap; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -81,7 +81,8 @@ impl<'tcx> TypeckRootCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; - let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); + let infcx = + tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); TypeckRootCtxt { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 8c943a961e76a..3eda3e9c67e85 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -28,7 +28,7 @@ use relate::lattice::{LatticeOp, LatticeOpKind}; use rustc_middle::bug; use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate; -use rustc_middle::ty::{Const, ImplSubject}; +use rustc_middle::ty::{Const, ImplSubject, TypingMode}; use super::*; use crate::infer::relate::type_relating::TypeRelating; @@ -67,30 +67,48 @@ impl<'tcx> InferCtxt<'tcx> { /// variables in the same state. This can be used to "branch off" many tests from the same /// common state. pub fn fork(&self) -> Self { - self.fork_with_intercrate(self.intercrate) + Self { + tcx: self.tcx, + typing_mode: self.typing_mode, + considering_regions: self.considering_regions, + skip_leak_check: self.skip_leak_check, + inner: self.inner.clone(), + lexical_region_resolutions: self.lexical_region_resolutions.clone(), + selection_cache: self.selection_cache.clone(), + evaluation_cache: self.evaluation_cache.clone(), + reported_trait_errors: self.reported_trait_errors.clone(), + reported_signature_mismatch: self.reported_signature_mismatch.clone(), + tainted_by_errors: self.tainted_by_errors.clone(), + universe: self.universe.clone(), + next_trait_solver: self.next_trait_solver, + obligation_inspector: self.obligation_inspector.clone(), + } } /// Forks the inference context, creating a new inference context with the same inference /// variables in the same state, except possibly changing the intercrate mode. This can be /// used to "branch off" many tests from the same common state. Used in negative coherence. - pub fn fork_with_intercrate(&self, intercrate: bool) -> Self { - Self { + pub fn fork_with_typing_mode(&self, typing_mode: TypingMode<'tcx>) -> Self { + // Unlike `fork`, this invalidates all cache entries as they may depend on the + // typing mode. + let forked = Self { tcx: self.tcx, - defining_opaque_types: self.defining_opaque_types, + typing_mode, considering_regions: self.considering_regions, skip_leak_check: self.skip_leak_check, inner: self.inner.clone(), lexical_region_resolutions: self.lexical_region_resolutions.clone(), - selection_cache: self.selection_cache.clone(), - evaluation_cache: self.evaluation_cache.clone(), + selection_cache: Default::default(), + evaluation_cache: Default::default(), reported_trait_errors: self.reported_trait_errors.clone(), reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), universe: self.universe.clone(), - intercrate, next_trait_solver: self.next_trait_solver, obligation_inspector: self.obligation_inspector.clone(), - } + }; + forked.inner.borrow_mut().projection_cache().clear(); + forked } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 90d07964fdac0..c9d8ebecef050 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> { V: TypeFoldable>, { let (param_env, value) = value.into_parts(); - let param_env = self.tcx.canonical_param_env_cache.get_or_insert( + let canonical_param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, query_state, @@ -64,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> { ); let canonical = Canonicalizer::canonicalize_with_base( - param_env, + canonical_param_env, value, Some(self), self.tcx, @@ -72,7 +72,7 @@ impl<'tcx> InferCtxt<'tcx> { query_state, ) .unchecked_map(|(param_env, value)| param_env.and(value)); - CanonicalQueryInput { canonical, defining_opaque_types: self.defining_opaque_types() } + CanonicalQueryInput { canonical, typing_mode: self.typing_mode(param_env) } } /// Canonicalizes a query *response* `V`. When we canonicalize a diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 0c151a11ad4e3..ecda9c6eb000a 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -1,7 +1,6 @@ ///! Definition of `InferCtxtLike` from the librarified type layer. -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; -use rustc_middle::traits::solve::SolverMode; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::combine::PredicateEmittingRelation; @@ -21,11 +20,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.next_trait_solver } - fn solver_mode(&self) -> ty::solve::SolverMode { - match self.intercrate { - true => SolverMode::Coherence, - false => SolverMode::Normal, - } + fn typing_mode( + &self, + param_env_for_debug_assertion: ty::ParamEnv<'tcx>, + ) -> ty::TypingMode<'tcx> { + self.typing_mode(param_env_for_debug_assertion) } fn universe(&self) -> ty::UniverseIndex { @@ -91,10 +90,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } - fn defining_opaque_types(&self) -> &'tcx ty::List { - self.defining_opaque_types() - } - fn next_ty_infer(&self) -> Ty<'tcx> { self.next_ty_var(DUMMY_SP) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index be43cba97f08f..fc54d69449f04 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -38,11 +38,12 @@ use rustc_middle::ty::fold::{ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, - GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, + GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_span::symbol::Symbol; +use rustc_type_ir::solve::Reveal; use snapshot::undo_log::InferCtxtUndoLogs; use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; @@ -243,8 +244,9 @@ impl<'tcx> InferCtxtInner<'tcx> { pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, - /// The `DefIds` of the opaque types that may have their hidden types constrained. - defining_opaque_types: &'tcx ty::List, + /// The mode of this inference context, see the struct documentation + /// for more details. + typing_mode: TypingMode<'tcx>, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -296,26 +298,6 @@ pub struct InferCtxt<'tcx> { /// bound. universe: Cell, - /// During coherence we have to assume that other crates may add - /// additional impls which we currently don't know about. - /// - /// To deal with this evaluation, we should be conservative - /// and consider the possibility of impls from outside this crate. - /// This comes up primarily when resolving ambiguity. Imagine - /// there is some trait reference `$0: Bar` where `$0` is an - /// inference variable. If `intercrate` is true, then we can never - /// say for sure that this reference is not implemented, even if - /// there are *no impls at all for `Bar`*, because `$0` could be - /// bound to some type that in a downstream crate that implements - /// `Bar`. - /// - /// Outside of coherence, we set this to false because we are only - /// interested in types that the user could actually have written. - /// In other words, we consider `$0: Bar` to be unimplemented if - /// there is no type that the user could *actually name* that - /// would satisfy it. This avoids crippling inference, basically. - pub intercrate: bool, - next_trait_solver: bool, pub obligation_inspector: Cell>>, @@ -529,11 +511,8 @@ pub struct RegionObligation<'tcx> { /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, - defining_opaque_types: &'tcx ty::List, considering_regions: bool, skip_leak_check: bool, - /// Whether we are in coherence mode. - intercrate: bool, /// Whether we should use the new trait solver in the local inference context, /// which affects things like which solver is used in `predicate_may_hold`. next_trait_solver: bool, @@ -544,37 +523,19 @@ impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, - defining_opaque_types: ty::List::empty(), considering_regions: true, skip_leak_check: false, - intercrate: false, next_trait_solver: self.next_trait_solver_globally(), } } } impl<'tcx> InferCtxtBuilder<'tcx> { - /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, - /// you need to call this function. Otherwise the opaque type will be treated opaquely. - /// - /// It is only meant to be called in two places, for typeck - /// (via `Inherited::build`) and for the inference context used - /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self { - self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor); - self - } - pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self { self.next_trait_solver = next_trait_solver; self } - pub fn intercrate(mut self, intercrate: bool) -> Self { - self.intercrate = intercrate; - self - } - pub fn ignoring_regions(mut self) -> Self { self.considering_regions = false; self @@ -600,24 +561,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> { where T: TypeFoldable>, { - self.defining_opaque_types = input.defining_opaque_types; - let infcx = self.build(); + let infcx = self.build(input.typing_mode); let (value, args) = infcx.instantiate_canonical(span, &input.canonical); (infcx, value, args) } - pub fn build(&mut self) -> InferCtxt<'tcx> { - let InferCtxtBuilder { - tcx, - defining_opaque_types, - considering_regions, - skip_leak_check, - intercrate, - next_trait_solver, - } = *self; + pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> { + let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } = + *self; InferCtxt { tcx, - defining_opaque_types, + typing_mode, considering_regions, skip_leak_check, inner: RefCell::new(InferCtxtInner::new()), @@ -628,7 +582,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), universe: Cell::new(ty::UniverseIndex::ROOT), - intercrate, next_trait_solver, obligation_inspector: Cell::new(None), } @@ -659,14 +612,30 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.dcx().taintable_handle(&self.tainted_by_errors) } - pub fn defining_opaque_types(&self) -> &'tcx ty::List { - self.defining_opaque_types - } - pub fn next_trait_solver(&self) -> bool { self.next_trait_solver } + #[inline(always)] + pub fn typing_mode( + &self, + param_env_for_debug_assertion: ty::ParamEnv<'tcx>, + ) -> TypingMode<'tcx> { + if cfg!(debug_assertions) { + match (param_env_for_debug_assertion.reveal(), self.typing_mode) { + (Reveal::All, TypingMode::PostAnalysis) + | (Reveal::UserFacing, TypingMode::Coherence | TypingMode::Analysis { .. }) => {} + (r, t) => unreachable!("TypingMode x Reveal mismatch: {r:?} {t:?}"), + } + } + self.typing_mode + } + + #[inline(always)] + pub fn typing_mode_unchecked(&self) -> TypingMode<'tcx> { + self.typing_mode + } + pub fn freshen>>(&self, t: T) -> T { t.fold_with(&mut self.freshener()) } @@ -1029,8 +998,12 @@ impl<'tcx> InferCtxt<'tcx> { #[inline(always)] pub fn can_define_opaque_ty(&self, id: impl Into) -> bool { - let Some(id) = id.into().as_local() else { return false }; - self.defining_opaque_types.contains(&id) + match self.typing_mode_unchecked() { + TypingMode::Analysis { defining_opaque_types } => { + id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) + } + TypingMode::Coherence | TypingMode::PostAnalysis => false, + } } pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index c38b7114e43eb..498d25aea640b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -2,6 +2,7 @@ use hir::def_id::{DefId, LocalDefId}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; +use rustc_middle::bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -100,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); - if self.intercrate { + if let ty::TypingMode::Coherence = self.typing_mode(param_env) { // See comment on `insert_hidden_type` for why this is sufficient in coherence return Some(self.register_hidden_type( OpaqueTypeKey { def_id, args }, @@ -519,28 +520,32 @@ impl<'tcx> InferCtxt<'tcx> { // value being folded. In simple cases like `-> impl Foo`, // these are the same span, but not in cases like `-> (impl // Foo, impl Bar)`. - if self.intercrate { - // During intercrate we do not define opaque types but instead always - // force ambiguity unless the hidden type is known to not implement - // our trait. - goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous)) - } else { - let prev = self - .inner - .borrow_mut() - .opaque_types() - .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); - if let Some(prev) = prev { - goals.extend( - self.at(&ObligationCause::dummy_with_span(span), param_env) - .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)? - .obligations - .into_iter() - // FIXME: Shuttling between obligations and goals is awkward. - .map(Goal::from), - ); + match self.typing_mode(param_env) { + ty::TypingMode::Coherence => { + // During intercrate we do not define opaque types but instead always + // force ambiguity unless the hidden type is known to not implement + // our trait. + goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous)); } - }; + ty::TypingMode::Analysis { .. } => { + let prev = self + .inner + .borrow_mut() + .opaque_types() + .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); + if let Some(prev) = prev { + goals.extend( + self.at(&ObligationCause::dummy_with_span(span), param_env) + .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)? + .obligations + .into_iter() + // FIXME: Shuttling between obligations and goals is awkward. + .map(Goal::from), + ); + } + } + ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"), + } Ok(()) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 32817dbcb2140..4c80bf4e07e8c 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::visit::MaxUniverse; use rustc_middle::ty::{ self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, + TypingMode, }; use rustc_span::Span; use tracing::{debug, instrument, warn}; @@ -519,7 +520,10 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // // cc trait-system-refactor-initiative#108 if self.infcx.next_trait_solver() - && !self.infcx.intercrate + && !matches!( + self.infcx.typing_mode_unchecked(), + TypingMode::Coherence + ) && self.in_alias { inner.type_variables().equate(vid, new_var_id); @@ -650,7 +654,10 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // See the comment for type inference variables // for more details. if self.infcx.next_trait_solver() - && !self.infcx.intercrate + && !matches!( + self.infcx.typing_mode_unchecked(), + TypingMode::Coherence + ) && self.in_alias { variable_table.union(vid, new_var_id); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index dbb8c66753236..77682ea9341b4 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -31,7 +31,7 @@ use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef}; use rustc_session::lint::FutureIncompatibilityReason; // hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; @@ -604,7 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { && cx .tcx .infer_ctxt() - .build() + .build(cx.typing_mode()) .type_implements_trait(iter_trait, [ty], cx.param_env) .must_apply_modulo_regions() { @@ -648,7 +648,9 @@ fn type_implements_negative_copy_modulo_regions<'tcx>( predicate: pred.upcast(tcx), }; - tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation) + tcx.infer_ctxt() + .build(TypingMode::non_body_analysis()) + .predicate_must_hold_modulo_regions(&obligation) } declare_lint! { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 699088914e87e..aa7ec2659d089 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -14,11 +14,12 @@ use rustc_feature::Features; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_infer::traits::Reveal; use rustc_middle::bug; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; -use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode}; use rustc_session::lint::{ BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, }; @@ -698,6 +699,15 @@ impl LintContext for EarlyContext<'_> { } impl<'tcx> LateContext<'tcx> { + /// The typing mode of the currently visited node. Use this when + /// building a new `InferCtxt`. + pub fn typing_mode(&self) -> TypingMode<'tcx> { + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + // FIXME(#132279): In case we're in a body, we should use a typing + // mode which reveals the opaque types defined by that body. + TypingMode::non_body_analysis() + } + /// Gets the type-checking results for the current body, /// or `None` if outside a body. pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index fcb7a6108c0e2..cf68e41243ff3 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>( } let ty = args.type_at(0); - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let ocx = ObligationCtxt::new(&infcx); let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index cc40b67ab271d..026826021c813 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; @@ -184,7 +184,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { }), outlives_env: LazyCell::new(|| { let param_env = tcx.param_env(parent_def_id); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let ocx = ObligationCtxt::new(&infcx); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); let implied_bounds = diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 51877e8a03495..cf25ec99e6713 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -157,7 +157,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String), ); - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let suggest_display = is_str || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| { infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index ffbcf7f808ebe..16a1a5a72bc49 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } let def_id = opaque.def_id.to_def_id(); - let infcx = &cx.tcx.infer_ctxt().build(); + let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode()); // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 564d274bc8b1e..57da5b39ba781 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -323,7 +323,7 @@ macro_rules! define_callbacks { // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(target_pointer_width = "64")] const _: () = { - if mem::size_of::>() > 72 { + if mem::size_of::>() > 80 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5ae9c589ec4a5..5cbbc80ebfbb6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -54,7 +54,6 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; pub use rustc_type_ir::lift::Lift; -use rustc_type_ir::solve::SolverMode; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph}; use tracing::{debug, trace}; @@ -170,15 +169,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { tracked.get(self) } - fn with_global_cache( - self, - mode: SolverMode, - f: impl FnOnce(&mut search_graph::GlobalCache) -> R, - ) -> R { - match mode { - SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()), - SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()), - } + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { + f(&mut *self.new_solver_evaluation_cache.lock()) } fn evaluation_is_concurrent(&self) -> bool { @@ -629,6 +621,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> ty::Binder<'tcx, T> { self.anonymize_bound_vars(binder) } + + fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes { + self.opaque_types_defined_by(defining_anchor) + } } macro_rules! bidirectional_lang_item_map { @@ -1334,7 +1330,6 @@ pub struct GlobalCtxt<'tcx> { /// Caches the results of goal evaluation in the new solver. pub new_solver_evaluation_cache: Lock>>, - pub new_solver_coherence_evaluation_cache: Lock>>, pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>, @@ -1561,7 +1556,6 @@ impl<'tcx> TyCtxt<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), new_solver_evaluation_cache: Default::default(), - new_solver_coherence_evaluation_cache: Default::default(), canonical_param_env_cache: Default::default(), data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b92fc864b49a7..bd32e5837b38f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -100,7 +100,7 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, - ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, + ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d8362ccc0a97c..a8327ebc17fee 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -40,6 +40,7 @@ pub type AliasTy<'tcx> = ir::AliasTy>; pub type FnSig<'tcx> = ir::FnSig>; pub type Binder<'tcx, T> = ir::Binder, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; +pub type TypingMode<'tcx> = ir::TypingMode>; pub trait Article { fn article(&self) -> &'static str; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 8c20d2e0d3a62..e15ea4d8d8be2 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -16,7 +16,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::query::TyCtxtAt; use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir}; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -500,7 +500,9 @@ fn construct_fn<'tcx>( ); } - let infcx = tcx.infer_ctxt().build(); + // FIXME(#132279): This should be able to reveal opaque + // types defined during HIR typeck. + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let mut builder = Builder::new( thir, infcx, @@ -578,7 +580,9 @@ fn construct_const<'a, 'tcx>( _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; - let infcx = tcx.infer_ctxt().build(); + // FIXME(#132279): We likely want to be able to use the hidden types of + // opaques used by this function here. + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let mut builder = Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0dfa9168f7c80..c89f526aa1758 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::Obligation; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::{FieldPat, Pat, PatKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree}; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::traits::ObligationCause; @@ -36,7 +36,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { id: hir::HirId, span: Span, ) -> Box> { - let infcx = self.tcx.infer_ctxt().build(); + // FIXME(#132279): We likely want to be able to reveal the hidden types + // of opaques defined in this function here. + let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let mut convert = ConstToPat::new(self, id, span, infcx); convert.to_pat(c, ty) } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index cd29105897778..ab3abc901b407 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -64,7 +64,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{ - self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, + self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::Analysis; @@ -1501,7 +1501,11 @@ fn check_field_tys_sized<'tcx>( return; } - let infcx = tcx.infer_ctxt().ignoring_regions().build(); + // FIXME(#132279): @lcnr believes that we may want to support coroutines + // whose `Sized`-ness relies on the hidden types of opaques defined by the + // parent function. In this case we'd have to be able to reveal only these + // opaques here. + let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); let param_env = tcx.param_env(def_id); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 25e68f44456b8..77356723c466b 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, - Variance, + TypingMode, Variance, }; use rustc_middle::{bug, span_bug}; use rustc_target::abi::{FIRST_VARIANT, Size}; @@ -606,7 +606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - let infcx = self.tcx.infer_ctxt().build(); + let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env)); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(Obligation::new( self.tcx, diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 4da1e7fa711b5..f7fbfed5b8e38 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_type_ir::fold::TypeFoldable; -use rustc_type_ir::solve::{Certainty, Goal, NoSolution, SolverMode}; +use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; pub trait SolverDelegate: Deref::Infcx> + Sized { @@ -15,7 +15,6 @@ pub trait SolverDelegate: Deref::Infcx> + Size fn build_with_canonical( cx: Self::Interner, - solver_mode: SolverMode, canonical: &ty::CanonicalQueryInput, ) -> (Self, V, ty::CanonicalVarValues) where @@ -93,7 +92,6 @@ pub trait SolverDelegate: Deref::Infcx> + Size fn fetch_eligible_assoc_item( &self, - param_env: ::ParamEnv, goal_trait_ref: ty::TraitRef, trait_assoc_def_id: ::DefId, impl_def_id: ::DefId, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index f6a5f20a639ec..ebf7372926f8a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -8,14 +8,14 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::inspect; use rustc_type_ir::visit::TypeVisitableExt as _; -use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate}; +use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate}; use tracing::{debug, instrument}; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, - MaybeCause, NoSolution, QueryResult, SolverMode, + MaybeCause, NoSolution, QueryResult, }; /// A candidate is a possible way to prove a goal. @@ -328,11 +328,12 @@ where let mut candidates = vec![]; - if self.solver_mode() == SolverMode::Coherence { + if let TypingMode::Coherence = self.typing_mode(goal.param_env) { if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { return vec![candidate]; } } + self.assemble_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); @@ -343,8 +344,11 @@ where self.assemble_param_env_candidates(goal, &mut candidates); - if self.solver_mode() == SolverMode::Normal { - self.discard_impls_shadowed_by_env(goal, &mut candidates); + match self.typing_mode(goal.param_env) { + TypingMode::Coherence => {} + TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { + self.discard_impls_shadowed_by_env(goal, &mut candidates); + } } candidates diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index e2fd0dd2a25fa..2f50070d43883 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -55,6 +55,7 @@ where &self, goal: Goal, ) -> (Vec, CanonicalInput) { + let param_env_for_debug_assertion = goal.param_env; let opaque_types = self.delegate.clone_opaque_types_for_query_response(); let (goal, opaque_types) = (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); @@ -73,7 +74,7 @@ where ); let query_input = ty::CanonicalQueryInput { canonical, - defining_opaque_types: self.delegate.defining_opaque_types(), + typing_mode: self.typing_mode(param_env_for_debug_assertion), }; (orig_values, query_input) } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 7608253882a27..8685896715e1e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -10,7 +10,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner}; +use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::{instrument, trace}; @@ -21,7 +21,6 @@ use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, - SolverMode, }; pub(super) mod canonical; @@ -215,8 +214,8 @@ where D: SolverDelegate, I: Interner, { - pub(super) fn solver_mode(&self) -> SolverMode { - self.search_graph.solver_mode() + pub(super) fn typing_mode(&self, param_env_for_debug_assertion: I::ParamEnv) -> TypingMode { + self.delegate.typing_mode(param_env_for_debug_assertion) } pub(super) fn set_is_normalizes_to_goal(&mut self) { @@ -232,7 +231,7 @@ where generate_proof_tree: GenerateProofTree, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option>) { - let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth); + let mut search_graph = SearchGraph::new(root_depth); let mut ecx = EvalCtxt { delegate, @@ -279,7 +278,7 @@ where f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal) -> R, ) -> R { let (ref delegate, input, var_values) = - SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input); + SolverDelegate::build_with_canonical(cx, &canonical_input); let mut ecx = EvalCtxt { delegate, @@ -942,21 +941,11 @@ where pub(super) fn fetch_eligible_assoc_item( &self, - param_env: I::ParamEnv, goal_trait_ref: ty::TraitRef, trait_assoc_def_id: I::DefId, impl_def_id: I::DefId, ) -> Result, NoSolution> { - self.delegate.fetch_eligible_assoc_item( - param_env, - goal_trait_ref, - trait_assoc_def_id, - impl_def_id, - ) - } - - pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool { - self.delegate.defining_opaque_types().contains(&def_id) + self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id) } pub(super) fn insert_hidden_type( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 7287cdf74bf45..129744b4db7e5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -6,7 +6,7 @@ mod weak_types; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; +use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate}; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, Reveal, + NoSolution, QueryResult, }; impl EvalCtxt<'_, D> @@ -71,21 +71,21 @@ where Ok(()) } ty::AliasTermKind::OpaqueTy => { - match param_env.reveal() { - // In user-facing mode, paques are only rigid if we may not define it. - Reveal::UserFacing => { + match self.typing_mode(param_env) { + // Opaques are never rigid outside of analysis mode. + TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution), + // During analysis, opaques are only rigid if we may not define it. + TypingMode::Analysis { defining_opaque_types } => { if rigid_alias .def_id .as_local() - .is_some_and(|def_id| self.can_define_opaque_ty(def_id)) + .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) { Err(NoSolution) } else { Ok(()) } } - // Opaques are never rigid in reveal-all mode. - Reveal::All => Err(NoSolution), } } // FIXME(generic_const_exprs): we would need to support generic consts here @@ -252,7 +252,6 @@ where // return ambiguity this would otherwise be incomplete, resulting in // unsoundness during coherence (#105782). let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item( - goal.param_env, goal_trait_ref, goal.predicate.def_id(), impl_def_id, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index f8d51f304f332..d1d701695ab83 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -4,12 +4,10 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_type_ir::inherent::*; -use rustc_type_ir::{self as ty, Interner}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use crate::delegate::SolverDelegate; -use crate::solve::{ - Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect, -}; +use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect}; impl EvalCtxt<'_, D> where @@ -24,17 +22,27 @@ where let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); - match (goal.param_env.reveal(), self.solver_mode()) { - (Reveal::UserFacing, SolverMode::Normal) => { - let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else { + match self.typing_mode(goal.param_env) { + TypingMode::Coherence => { + // An impossible opaque type bound is the only way this goal will fail + // e.g. assigning `impl Copy := NotCopy` + self.add_item_bounds_for_hidden_type( + opaque_ty.def_id, + opaque_ty.args, + goal.param_env, + expected, + ); + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + TypingMode::Analysis { defining_opaque_types } => { + let Some(def_id) = opaque_ty.def_id.as_local() else { return Err(NoSolution); }; - // FIXME: at some point we should call queries without defining - // new opaque types but having the existing opaque type definitions. - // This will require moving this below "Prefer opaques registered already". - if !self.can_define_opaque_ty(opaque_ty_def_id) { + + if !defining_opaque_types.contains(&def_id) { return Err(NoSolution); } + // FIXME: This may have issues when the args contain aliases... match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) { Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { @@ -48,8 +56,7 @@ where Ok(()) => {} } // Prefer opaques registered already. - let opaque_type_key = - ty::OpaqueTypeKey { def_id: opaque_ty_def_id, args: opaque_ty.args }; + let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args }; // FIXME: This also unifies the previous hidden type with the expected. // // If that fails, we insert `expected` as a new hidden type instead of @@ -69,7 +76,7 @@ where } ecx.eq(goal.param_env, candidate_ty, expected)?; ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.into(), + def_id.into(), candidate_key.args, goal.param_env, candidate_ty, @@ -82,25 +89,14 @@ where // FIXME: should we use `inject_hidden_type_unchecked` here? self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?; self.add_item_bounds_for_hidden_type( - opaque_ty.def_id, + def_id.into(), opaque_ty.args, goal.param_env, expected, ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - (Reveal::UserFacing, SolverMode::Coherence) => { - // An impossible opaque type bound is the only way this goal will fail - // e.g. assigning `impl Copy := NotCopy` - self.add_item_bounds_for_hidden_type( - opaque_ty.def_id, - opaque_ty.args, - goal.param_env, - expected, - ); - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } - (Reveal::All, _) => { + TypingMode::PostAnalysis => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); self.eq(goal.param_env, expected, actual)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 08cc89d950e22..9b63c6cc68e6e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -6,7 +6,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::visit::TypeVisitableExt as _; -use rustc_type_ir::{self as ty, Interner, TraitPredicate, Upcast as _, elaborate}; +use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate}; use tracing::{instrument, trace}; use crate::delegate::SolverDelegate; @@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate}; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, Reveal, SolverMode, + NoSolution, QueryResult, }; impl assembly::GoalKind for TraitPredicate @@ -67,9 +67,9 @@ where let maximal_certainty = match (impl_polarity, goal.predicate.polarity) { // In intercrate mode, this is ambiguous. But outside of intercrate, // it's not a real impl. - (ty::ImplPolarity::Reservation, _) => match ecx.solver_mode() { - SolverMode::Coherence => Certainty::AMBIGUOUS, - SolverMode::Normal => return Err(NoSolution), + (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode(goal.param_env) { + TypingMode::Coherence => Certainty::AMBIGUOUS, + TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), }, // Impl matches polarity @@ -167,33 +167,32 @@ where return result; } - // Don't call `type_of` on a local TAIT that's in the defining scope, - // since that may require calling `typeck` on the same item we're + // We only look into opaque types during analysis for opaque types + // outside of their defining scope. Doing so for opaques in the + // defining scope may require calling `typeck` on the same item we're // currently type checking, which will result in a fatal cycle that // ideally we want to avoid, since we can make progress on this goal // via an alias bound or a locally-inferred hidden type instead. - // - // Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since - // we already normalize the self type in - // `assemble_candidates_after_normalizing_self_ty`, and we'd - // just be registering an identical candidate here. - // - // We always return `Err(NoSolution)` here in `SolverMode::Coherence` - // since we'll always register an ambiguous candidate in - // `assemble_candidates_after_normalizing_self_ty` due to normalizing - // the TAIT. if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { - if matches!(goal.param_env.reveal(), Reveal::All) - || matches!(ecx.solver_mode(), SolverMode::Coherence) - || opaque_ty - .def_id - .as_local() - .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) - { - return Err(NoSolution); + match ecx.typing_mode(goal.param_env) { + TypingMode::Coherence | TypingMode::PostAnalysis => { + unreachable!("rigid opaque outside of analysis: {goal:?}"); + } + TypingMode::Analysis { defining_opaque_types } => { + if opaque_ty + .def_id + .as_local() + .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) + { + return Err(NoSolution); + } + } } } + // We want to make sure + debug_assert!(!matches!(ecx.typing_mode(), TypingMode::Coherence)); + ecx.probe_and_evaluate_goal_for_constituent_tys( CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8c4592cbb369f..0a2926c040447 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -25,7 +25,7 @@ use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, @@ -2267,7 +2267,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let def_id = hir_id.expect_owner().def_id; let param_env = ty::ParamEnv::empty(); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let span = tcx.def_span(def_id); diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 0b6cf82ca8b46..921a915d05b14 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -2,6 +2,7 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; use rustc_ast::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_middle::infer::canonical::ir::TypingMode; use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; @@ -54,7 +55,7 @@ pub fn ensure_wf<'tcx>( param_env, pred, ); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 5793ac2fc313c..c53689b211d2a 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -7,13 +7,13 @@ use rustc_infer::infer::canonical::{ Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues, }; use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt}; +use rustc_infer::traits::ObligationCause; use rustc_infer::traits::solve::Goal; -use rustc_infer::traits::{ObligationCause, Reveal}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; -use rustc_type_ir::solve::{Certainty, NoSolution, SolverMode}; -use tracing::trace; +use rustc_type_ir::TypingMode; +use rustc_type_ir::solve::{Certainty, NoSolution}; use crate::traits::specialization_graph; @@ -47,7 +47,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< fn build_with_canonical( interner: TyCtxt<'tcx>, - solver_mode: SolverMode, canonical: &CanonicalQueryInput<'tcx, V>, ) -> (Self, V, CanonicalVarValues<'tcx>) where @@ -56,10 +55,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< let (infcx, value, vars) = interner .infer_ctxt() .with_next_trait_solver(true) - .intercrate(match solver_mode { - SolverMode::Normal => false, - SolverMode::Coherence => true, - }) .build_with_canonical(DUMMY_SP, canonical); (SolverDelegate(infcx), value, vars) } @@ -195,7 +190,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< fn fetch_eligible_assoc_item( &self, - param_env: ty::ParamEnv<'tcx>, goal_trait_ref: ty::TraitRef<'tcx>, trait_assoc_def_id: DefId, impl_def_id: DefId, @@ -211,12 +205,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< // and the obligation is monomorphic, otherwise passes such as // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. - if param_env.reveal() == Reveal::All { - let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); - !poly_trait_ref.still_further_specializable() - } else { - trace!(?node_item.item.def_id, "not eligible due to default"); - false + match self.typing_mode_unchecked() { + TypingMode::Coherence | TypingMode::Analysis { .. } => false, + TypingMode::PostAnalysis => { + let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); + !poly_trait_ref.still_further_specializable() + } } }; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 934fe9ec47c0e..52ba5621d3191 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -10,6 +10,7 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::{Region, RegionVid}; use tracing::debug; +use ty::TypingMode; use super::*; use crate::errors::UnableToConstructConstantValue; @@ -79,7 +80,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let mut selcx = SelectionContext::new(&infcx); for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] { let result = selcx.select(&Obligation::new( @@ -99,7 +100,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } } - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let mut fresh_preds = FxIndexSet::default(); // Due to the way projections are handled by SelectionContext, we need to run diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f8fb297e36c4b..3cd11d7c8e8de 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -18,7 +18,7 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; pub use rustc_next_trait_solver::coherence::*; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use rustc_span::symbol::sym; @@ -195,9 +195,8 @@ fn overlap<'tcx>( let infcx = tcx .infer_ctxt() .skip_leak_check(skip_leak_check.is_yes()) - .intercrate(true) .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) - .build(); + .build(TypingMode::Coherence); let selcx = &mut SelectionContext::new(&infcx); if track_ambiguity_causes.is_yes() { selcx.enable_tracking_intercrate_ambiguity_causes(); @@ -419,7 +418,7 @@ fn impl_intersection_has_negative_obligation( // N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates // do not need intercrate mode enabled. - let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build(); + let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::Coherence); let root_universe = infcx.universe(); assert_eq!(root_universe, ty::UniverseIndex::ROOT); @@ -570,7 +569,9 @@ fn try_prove_negated_where_clause<'tcx>( // the *existence* of a negative goal, not the non-existence of a positive goal. // Without this, we over-eagerly register coherence ambiguity candidates when // impl candidates do exist. - let ref infcx = root_infcx.fork_with_intercrate(false); + // FIXME(#132279): `TypingMode::non_body_analysis` is a bit questionable here as it + // would cause us to reveal opaque types to leak their auto traits. + let ref infcx = root_infcx.fork_with_typing_mode(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new(infcx); ocx.register_obligation(Obligation::new( infcx.tcx, @@ -714,7 +715,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // It is only relevant that a goal is unknowable if it would have otherwise // failed. - let non_intercrate_infcx = infcx.fork_with_intercrate(false); + // FIXME(#132279): Forking with `TypingMode::non_body_analysis` is a bit questionable + // as it would allow us to reveal opaque types, potentially causing unexpected + // cycles. + let non_intercrate_infcx = infcx.fork_with_typing_mode(TypingMode::non_body_analysis()); if non_intercrate_infcx.predicate_may_hold(&Obligation::new( infcx.tcx, ObligationCause::dummy(), diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index a068f25fe35ec..bd4e3dd7d8ddc 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -14,7 +14,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, Upcast, + TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; use rustc_span::symbol::Symbol; @@ -718,7 +718,7 @@ fn receiver_is_dispatchable<'tcx>( Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) }; - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); // the receiver is dispatchable iff the obligation holds infcx.predicate_must_hold_modulo_regions(&obligation) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e3ad21e352a06..29e60e3c428bc 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -13,7 +13,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt}; +use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode}; use thin_vec::ThinVec; use tracing::{debug, debug_span, instrument}; @@ -760,7 +760,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let infcx = self.selcx.infcx; - if obligation.predicate.is_global() && !self.selcx.is_intercrate() { + if obligation.predicate.is_global() + && !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence) + { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { @@ -813,11 +815,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let tcx = self.selcx.tcx(); - - if obligation.predicate.is_global() && !self.selcx.is_intercrate() { + let infcx = self.selcx.infcx; + if obligation.predicate.is_global() + && !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence) + { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) { + if infcx.predicate_must_hold_considering_regions(obligation) { if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation( &mut self.selcx, &project_obligation, @@ -825,8 +829,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { // If `predicate_must_hold_considering_regions` succeeds, then we've // evaluated all sub-obligations. We can therefore mark the 'root' // obligation as complete, and skip evaluating sub-obligations. - self.selcx - .infcx + infcx .inner .borrow_mut() .projection_cache() diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 3e65194577e0d..3b17fa6b03285 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; -use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use super::outlives_bounds::InferCtxtExt; use crate::regions::InferCtxtRegionExt; @@ -143,7 +143,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( let mut infringing_inner_tys = vec![]; for inner_ty in inner_tys { // We use an ocx per inner ty for better diagnostics - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); ocx.register_bound( @@ -200,7 +200,7 @@ pub fn all_fields_implement_trait<'tcx>( for variant in adt.variants() { for field in &variant.fields { // Do this per-field to get better error messages. - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let unnormalized_ty = field.ty(tcx, args); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f5d9b50359c13..1c84f2171bcac 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -34,7 +34,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast, + self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, TypingMode, + Upcast, }; use rustc_span::Span; use rustc_span::def_id::DefId; @@ -274,7 +275,7 @@ fn do_normalize_predicates<'tcx>( // by wfcheck anyway, so I'm not sure we have to check // them here too, and we will remove this function when // we move over to lazy normalization *anyway*. - let infcx = tcx.infer_ctxt().ignoring_regions().build(); + let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let predicates = ocx.normalize(&cause, elaborated_env, predicates); @@ -475,11 +476,11 @@ pub fn normalize_param_env_or_error<'tcx>( /// Normalizes the predicates and checks whether they hold in an empty environment. If this /// returns true, then either normalize encountered an error or one of the predicates did not -/// hold. Used when creating vtables to check for unsatisfiable methods. +/// hold. Used when creating vtables to check for unsatisfiable methods. This should not be +/// used during analysis. pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec>) -> bool { debug!("impossible_predicates(predicates={:?})", predicates); - - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let param_env = ty::ParamEnv::reveal_all(); let ocx = ObligationCtxt::new(&infcx); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); @@ -568,8 +569,11 @@ fn is_impossible_associated_item( // since that method *may* have some substitutions where the predicates hold. // // This replicates the logic we use in coherence. - let infcx = - tcx.infer_ctxt().ignoring_regions().with_next_trait_solver(true).intercrate(true).build(); + let infcx = tcx + .infer_ctxt() + .ignoring_regions() + .with_next_trait_solver(true) + .build(TypingMode::Coherence); let param_env = ty::ParamEnv::empty(); let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0803dd74b89bb..a75c07c2e8c6e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -334,11 +334,6 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( ) -> Result>, InProgress> { let infcx = selcx.infcx; debug_assert!(!selcx.infcx.next_trait_solver()); - // Don't use the projection cache in intercrate mode - - // the `infcx` may be re-used between intercrate in non-intercrate - // mode, which could lead to using incorrect cache results. - let use_cache = !selcx.is_intercrate(); - let projection_term = infcx.resolve_vars_if_possible(projection_term); let cache_key = ProjectionCacheKey::new(projection_term, param_env); @@ -349,13 +344,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( // would not benefit from caching when proving `T: Trait` // bounds. It might be the case that we want two distinct caches, // or else another kind of cache entry. - - let cache_result = if use_cache { - infcx.inner.borrow_mut().projection_cache().try_start(cache_key) - } else { - Ok(()) - }; - match cache_result { + let cache_entry = infcx.inner.borrow_mut().projection_cache().try_start(cache_key); + match cache_entry { Ok(()) => debug!("no cache"), Err(ProjectionCacheEntry::Ambiguous) => { // If we found ambiguity the last time, that means we will continue @@ -378,10 +368,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( // Cache that normalizing this projection resulted in a cycle. This // should ensure that, unless this happens within a snapshot that's // rolled back, fulfillment or evaluation will notice the cycle. - - if use_cache { - infcx.inner.borrow_mut().projection_cache().recur(cache_key); - } + infcx.inner.borrow_mut().projection_cache().recur(cache_key); return Err(InProgress); } Err(ProjectionCacheEntry::Recur) => { @@ -445,26 +432,20 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( let mut deduped = SsoHashSet::with_capacity(result.obligations.len()); result.obligations.retain(|obligation| deduped.insert(obligation.clone())); - if use_cache { - infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); - } + infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); obligations.extend(result.obligations); Ok(Some(result.value)) } Ok(Projected::NoProgress(projected_ty)) => { let result = Normalized { value: projected_ty, obligations: PredicateObligations::new() }; - if use_cache { - infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); - } + infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); // No need to extend `obligations`. Ok(Some(result.value)) } Err(ProjectionError::TooManyCandidates) => { debug!("opt_normalize_projection_type: too many candidates"); - if use_cache { - infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); - } + infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); Ok(None) } Err(ProjectionError::TraitSelectionError(_)) => { @@ -473,10 +454,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( // just return `ty::err` but add the obligation `T : // Trait`, which when processed will cause the error to be // reported later - - if use_cache { - infcx.inner.borrow_mut().projection_cache().error(cache_key); - } + infcx.inner.borrow_mut().projection_cache().error(cache_key); let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); Ok(Some(result.value)) diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index bb44645a4ce1c..9e1a2a3e7d286 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -87,7 +87,6 @@ impl<'tcx> InferCtxt<'tcx> { Ok(result) }) } else { - assert!(!self.intercrate); let c_pred = self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values); self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e027586563ecc..03fde1d159890 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -16,7 +16,7 @@ use rustc_infer::traits::{ Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError, }; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -790,7 +790,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // Note that this is only sound as projection candidates of opaque types // are always applicable for auto traits. - } else if self.infcx.intercrate { + } else if let TypingMode::Coherence = + self.infcx.typing_mode(obligation.param_env) + { // We do not emit auto trait candidates for opaque types in coherence. // Doing so can result in weird dependency cycles. candidates.ambiguous = true; @@ -930,7 +932,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Option> { // Don't drop any candidates in intercrate mode, as it's incomplete. // (Not that it matters, since `Unsize` is not a stable trait.) - if self.infcx.intercrate { + // + // FIXME(@lcnr): This should probably only trigger during analysis, + // disabling candidates during codegen is also questionable. + if let TypingMode::Coherence = self.infcx.typing_mode(param_env) { return None; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 635d3bc99b1ad..b1e5e5263151e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2,6 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection +use std::assert_matches::assert_matches; use std::cell::{Cell, RefCell}; use std::fmt::{self, Display}; use std::ops::ControlFlow; @@ -28,7 +29,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, - Upcast, + TypingMode, Upcast, }; use rustc_span::Symbol; use rustc_span::symbol::sym; @@ -222,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Enables tracking of intercrate ambiguity causes. See /// the documentation of [`Self::intercrate_ambiguity_causes`] for more. pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { - assert!(self.is_intercrate()); + assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence); assert!(self.intercrate_ambiguity_causes.is_none()); self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); @@ -234,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn take_intercrate_ambiguity_causes( &mut self, ) -> FxIndexSet> { - assert!(self.is_intercrate()); + assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence); self.intercrate_ambiguity_causes.take().unwrap_or_default() } @@ -242,10 +243,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.tcx } - pub fn is_intercrate(&self) -> bool { - self.infcx.intercrate - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -1029,7 +1026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: PolyTraitObligation<'tcx>, ) -> Result { - if !self.is_intercrate() + if !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence) && obligation.is_global() && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param()) { @@ -1312,14 +1309,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { - // Neither the global nor local cache is aware of intercrate - // mode, so don't do any caching. In particular, we might - // re-use the same `InferCtxt` with both an intercrate - // and non-intercrate `SelectionContext` - if self.is_intercrate() { - return None; - } - let tcx = self.tcx(); if self.can_use_global_caches(param_env) { if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { @@ -1342,14 +1331,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - // Neither the global nor local cache is aware of intercrate - // mode, so don't do any caching. In particular, we might - // re-use the same `InferCtxt` with both an intercrate - // and non-intercrate `SelectionContext` - if self.is_intercrate() { - return; - } - if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value @@ -1476,13 +1457,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> { - debug!("is_knowable(intercrate={:?})", self.is_intercrate()); - - if !self.is_intercrate() { - return Ok(()); + let obligation = &stack.obligation; + match self.infcx.typing_mode(obligation.param_env) { + TypingMode::Coherence => {} + TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()), } - let obligation = &stack.obligation; + debug!("is_knowable()"); + let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); // Okay to skip binder because of the nature of the @@ -1502,25 +1484,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return false; } - // Avoid using the global cache during coherence and just rely - // on the local cache. This effectively disables caching - // during coherence. It is really just a simplification to - // avoid us having to fear that coherence results "pollute" - // the master cache. Since coherence executes pretty quickly, - // it's not worth going to more trouble to increase the - // hit-rate, I don't think. - if self.is_intercrate() { - return false; - } - - // Avoid using the global cache when we're defining opaque types - // as their hidden type may impact the result of candidate selection. - if !self.infcx.defining_opaque_types().is_empty() { - return false; + match self.infcx.typing_mode(param_env) { + // Avoid using the global cache during coherence and just rely + // on the local cache. It is really just a simplification to + // avoid us having to fear that coherence results "pollute" + // the master cache. Since coherence executes pretty quickly, + // it's not worth going to more trouble to increase the + // hit-rate, I don't think. + TypingMode::Coherence => false, + // Avoid using the global cache when we're defining opaque types + // as their hidden type may impact the result of candidate selection. + TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(), + // The global cache is only used if there are no opaque types in + // the defining scope or we're outside of analysis. + // + // FIXME(#132279): This is still incorrect as we treat opaque types + // and default associated items differently between these two modes. + TypingMode::PostAnalysis => true, } - - // Otherwise, we can use the global cache. - true } fn check_candidate_cache( @@ -1528,13 +1509,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { - // Neither the global nor local cache is aware of intercrate - // mode, so don't do any caching. In particular, we might - // re-use the same `InferCtxt` with both an intercrate - // and non-intercrate `SelectionContext` - if self.is_intercrate() { - return None; - } let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); @@ -1566,13 +1540,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &self, result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) -> bool { - // Neither the global nor local cache is aware of intercrate - // mode, so don't do any caching. In particular, we might - // re-use the same `InferCtxt` with both an intercrate - // and non-intercrate `SelectionContext` - if self.is_intercrate() { - return false; - } match result { Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(), _ => true, @@ -2541,7 +2508,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { })?; nested_obligations.extend(obligations); - if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation { + if impl_trait_header.polarity == ty::ImplPolarity::Reservation + && !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence) + { debug!("reservation impls only apply in intercrate mode"); return Err(()); } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 0e45f7a195f04..5bf3dbcbc3273 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -19,7 +19,9 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::bug; use rustc_middle::query::LocalCrate; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt, TypingMode, +}; use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym}; use specialization_graph::GraphExt; @@ -184,7 +186,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, let penv = tcx.param_env(impl1_def_id); // Create an infcx, taking the predicates of impl1 as assumptions: - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); // Attempt to prove that impl2 applies, given all of the above. fulfill_implication( diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index ed221e2a1835f..bb56d6eaf544f 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -9,7 +9,8 @@ use rustc_infer::traits::util::PredicateSet; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry, + self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, + VtblEntry, }; use rustc_span::{DUMMY_SP, Span, sym}; use smallvec::{SmallVec, smallvec}; @@ -439,7 +440,7 @@ fn trait_refs_are_compatible<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let param_env = ty::ParamEnv::reveal_all(); let ocx = ObligationCtxt::new(&infcx); let hr_source_principal = diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 1118219824652..d8c1c50d79a85 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, @@ -30,7 +30,7 @@ pub(crate) fn codegen_select_candidate<'tcx>( // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let infcx = tcx.infer_ctxt().ignoring_regions().build(); + let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env)); let mut selcx = SelectionContext::new(&infcx); let obligation_cause = ObligationCause::dummy(); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 3e2794f6489f8..d79059a39a1d1 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,7 +1,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use tracing::debug; @@ -22,7 +22,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par goal: ParamEnvAnd<'tcx, T>, ) -> Result { let ParamEnvAnd { param_env, value } = goal; - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).query_normalize(value) { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index 51b908881eb49..c26b41d896005 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -3,7 +3,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_trait_selection::traits; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { @@ -29,7 +29,7 @@ fn is_item_raw<'tcx>( ) -> bool { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(item, None); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id) } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 9b764133f2c6a..e258b6dae0b46 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -6,7 +6,7 @@ use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::util::AsyncDropGlueMorphology; -use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::sym; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; @@ -130,7 +130,7 @@ fn resolve_associated_item<'tcx>( .unwrap_or_else(|| { bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let param_env = param_env.with_reveal_all_normalized(tcx); let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); let args = translate_args( diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs index 1ead7b731e76c..0b4efab1d9c44 100644 --- a/compiler/rustc_ty_utils/src/structural_match.rs +++ b/compiler/rustc_ty_utils/src/structural_match.rs @@ -1,7 +1,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; /// This method returns true if and only if `adt_ty` itself has been marked as @@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; /// Note that this does *not* recursively check if the substructure of `adt_ty` /// implements the trait. fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool { - let infcx = &tcx.infer_ctxt().build(); + let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = ObligationCause::dummy(); let ocx = ObligationCtxt::new(infcx); diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 3fb7d87bcc4bc..24b2ebc1fbe79 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -8,7 +8,7 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; -use crate::{self as ty, Interner, UniverseIndex}; +use crate::{self as ty, Interner, TypingMode, UniverseIndex}; #[derive_where(Clone; I: Interner, V: Clone)] #[derive_where(Hash; I: Interner, V: Hash)] @@ -19,7 +19,7 @@ use crate::{self as ty, Interner, UniverseIndex}; #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct CanonicalQueryInput { pub canonical: Canonical, - pub defining_opaque_types: I::DefiningOpaqueTypes, + pub typing_mode: TypingMode, } /// A "canonicalized" type `V` is one where all free inference diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 7c6a3c65ebfb4..22223e4a8900a 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,9 +1,68 @@ +use derive_where::derive_where; +#[cfg(feature = "nightly")] +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; + use crate::fold::TypeFoldable; +use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::solve::SolverMode; +use crate::solve::Reveal; use crate::{self as ty, Interner}; +/// The current typing mode of an inference context. We unfortunately have some +/// slightly different typing rules depending on the current context. See the +/// doc comment for each variant for how and why they are used. +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +pub enum TypingMode { + /// When checking whether impls overlap, we check whether any obligations + /// are guaranteed to never hold when unifying the impls. This requires us + /// to be complete: we must never fail to prove something which may actually + /// hold. + /// + /// In this typing mode we bail with ambiguity in case its not knowable + /// whether a trait goal may hold, e.g. because the trait may get implemented + /// in a downstream or sibling crate. + /// + /// We also have to be careful when generalizing aliases inside of higher-ranked + /// types to not unnecessarily constrain any inference variables. + Coherence, + /// Analysis includes type inference, checking that items are well-formed, and + /// pretty much everything else which may emit proper type errors to the user. + /// + /// We only normalize opaque types which may get defined by the current body, + /// which are stored in `defining_opaque_types`. + Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, + /// After analysis, mostly during codegen and MIR optimizations, we're able to + /// reveal all opaque types. + PostAnalysis, +} + +impl TypingMode { + /// Analysis outside of a body does not define any opaque types. + pub fn non_body_analysis() -> TypingMode { + TypingMode::Analysis { defining_opaque_types: Default::default() } + } + + /// While typechecking a body, we need to be able to define the opaque + /// types defined by that body. + pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode { + TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } + } + + /// FIXME(#132279): Using this function is questionable as the `param_env` + /// does not track `defining_opaque_types` and whether we're in coherence mode. + /// Many uses of this function should also use a not-yet implemented typing mode + /// which reveals already defined opaque types in the future. This function will + /// get completely removed at some point. + pub fn from_param_env(param_env: I::ParamEnv) -> TypingMode { + match param_env.reveal() { + Reveal::UserFacing => TypingMode::non_body_analysis(), + Reveal::All => TypingMode::PostAnalysis, + } + } +} + pub trait InferCtxtLike: Sized { type Interner: Interner; fn cx(&self) -> Self::Interner; @@ -16,7 +75,10 @@ pub trait InferCtxtLike: Sized { true } - fn solver_mode(&self) -> SolverMode; + fn typing_mode( + &self, + param_env_for_debug_assertion: ::ParamEnv, + ) -> TypingMode; fn universe(&self) -> ty::UniverseIndex; fn create_next_universe(&self) -> ty::UniverseIndex; @@ -43,8 +105,6 @@ pub trait InferCtxtLike: Sized { vid: ty::RegionVid, ) -> ::Region; - fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes; - fn next_ty_infer(&self) -> ::Ty; fn next_const_infer(&self) -> ::Const; fn fresh_args_for_item( diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 6a8113b38b7bd..36ddddccfa253 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -11,9 +11,7 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; -use crate::solve::{ - CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode, -}; +use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, search_graph}; @@ -130,11 +128,7 @@ pub trait Interner: type Clause: Clause; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; - fn with_global_cache( - self, - mode: SolverMode, - f: impl FnOnce(&mut search_graph::GlobalCache) -> R, - ) -> R; + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R; fn evaluation_is_concurrent(&self) -> bool; @@ -298,6 +292,11 @@ pub trait Interner: self, binder: ty::Binder, ) -> ty::Binder; + + fn opaque_types_defined_by( + self, + defining_anchor: Self::LocalDefId, + ) -> Self::DefiningOpaqueTypes; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` @@ -414,12 +413,8 @@ impl search_graph::Cx for I { fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, I::DepNodeIndex) { I::with_cached_task(self, task) } - fn with_global_cache( - self, - mode: SolverMode, - f: impl FnOnce(&mut search_graph::GlobalCache) -> R, - ) -> R { - I::with_global_cache(self, mode, f) + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { + I::with_global_cache(self, f) } fn evaluation_is_concurrent(&self) -> bool { self.evaluation_is_concurrent() diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 17a3912730f57..53751f7711a71 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -6,9 +6,9 @@ use super::{ }; use crate::error::TypeError; use crate::inherent::*; -use crate::solve::{Goal, SolverMode}; +use crate::solve::Goal; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, InferCtxtLike, Interner, Upcast}; +use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast}; pub trait PredicateEmittingRelation::Interner>: TypeRelation @@ -128,19 +128,19 @@ where } (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { - match infcx.solver_mode() { - SolverMode::Normal => { - assert!(!infcx.next_trait_solver()); - structurally_relate_tys(relation, a, b) - } + assert!(!infcx.next_trait_solver()); + match infcx.typing_mode(relation.param_env()) { // During coherence, opaque types should be treated as *possibly* - // equal to any other type (except for possibly itinfcx). This is an + // equal to any other type. This is an // extremely heavy hammer, but can be relaxed in a forwards-compatible // way later. - SolverMode::Coherence => { + TypingMode::Coherence => { relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); Ok(a) } + TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { + structurally_relate_tys(relation, a, b) + } } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 3fd2bb61ba583..5010fc09adc39 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -22,7 +22,6 @@ use rustc_index::{Idx, IndexVec}; use tracing::debug; use crate::data_structures::HashMap; -use crate::solve::SolverMode; mod global_cache; use global_cache::CacheData; @@ -48,11 +47,7 @@ pub trait Cx: Copy { fn get_tracked(self, tracked: &Self::Tracked) -> T; fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex); - fn with_global_cache( - self, - mode: SolverMode, - f: impl FnOnce(&mut GlobalCache) -> R, - ) -> R; + fn with_global_cache(self, f: impl FnOnce(&mut GlobalCache) -> R) -> R; fn evaluation_is_concurrent(&self) -> bool; } @@ -358,7 +353,6 @@ struct ProvisionalCacheEntry { } pub struct SearchGraph, X: Cx = ::Cx> { - mode: SolverMode, root_depth: AvailableDepth, /// The stack of goals currently being computed. /// @@ -374,9 +368,8 @@ pub struct SearchGraph, X: Cx = ::Cx> { } impl, X: Cx> SearchGraph { - pub fn new(mode: SolverMode, root_depth: usize) -> SearchGraph { + pub fn new(root_depth: usize) -> SearchGraph { Self { - mode, root_depth: AvailableDepth(root_depth), stack: Default::default(), provisional_cache: Default::default(), @@ -384,10 +377,6 @@ impl, X: Cx> SearchGraph { } } - pub fn solver_mode(&self) -> SolverMode { - self.mode - } - /// Lazily update the stack entry for the parent goal. /// This behavior is shared between actually evaluating goals /// and using existing global cache entries to make sure they @@ -829,7 +818,7 @@ impl, X: Cx> SearchGraph { input: X::Input, available_depth: AvailableDepth, ) -> Option { - cx.with_global_cache(self.mode, |cache| { + cx.with_global_cache(|cache| { cache .get(cx, input, available_depth, |nested_goals| { Self::candidate_is_applicable( @@ -852,7 +841,7 @@ impl, X: Cx> SearchGraph { input: X::Input, available_depth: AvailableDepth, ) -> Option { - cx.with_global_cache(self.mode, |cache| { + cx.with_global_cache(|cache| { let CacheData { result, additional_depth, encountered_overflow, nested_goals } = cache .get(cx, input, available_depth, |nested_goals| { Self::candidate_is_applicable( @@ -1041,7 +1030,7 @@ impl, X: Cx> SearchGraph { ) { let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len(); debug!(?final_entry, ?result, "insert global cache"); - cx.with_global_cache(self.mode, |cache| { + cx.with_global_cache(|cache| { cache.insert( cx, input, diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index b3f8390bbf062..fe4558730513a 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -58,19 +58,6 @@ pub enum Reveal { All, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum SolverMode { - /// Ordinary trait solving, using everywhere except for coherence. - Normal, - /// Trait solving during coherence. There are a few notable differences - /// between coherence and ordinary trait solving. - /// - /// Most importantly, trait solving during coherence must not be incomplete, - /// i.e. return `Err(NoSolution)` for goals for which a solution exists. - /// This means that we must not make any guesses or arbitrary choices. - Coherence, -} - pub type CanonicalInput::Predicate> = ty::CanonicalQueryInput>; pub type CanonicalResponse = Canonical>; From ce22ccb55233dbf3d19c8a6796828ef24d6e9095 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 24 Oct 2024 12:00:55 +0200 Subject: [PATCH 05/13] remove outdated debug_assertion --- compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 9b63c6cc68e6e..e23e475a2a62a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -190,9 +190,6 @@ where } } - // We want to make sure - debug_assert!(!matches!(ecx.typing_mode(), TypingMode::Coherence)); - ecx.probe_and_evaluate_goal_for_constituent_tys( CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, From 4f3a73a42c5571e9985ad18a00b8a9decdd53281 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 24 Oct 2024 10:47:30 +0200 Subject: [PATCH 06/13] update tools --- src/librustdoc/clean/blanket_impl.rs | 4 ++-- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/html/format.rs | 5 ++--- src/tools/clippy/clippy_lints/src/eta_reduction.rs | 5 +++-- .../clippy/clippy_lints/src/functions/must_use.rs | 2 +- src/tools/clippy/clippy_lints/src/future_not_send.rs | 2 +- .../clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 2 +- src/tools/clippy/clippy_lints/src/no_effect.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 2 +- .../clippy/clippy_lints/src/useless_conversion.rs | 2 +- .../clippy/clippy_utils/src/qualify_min_const_fn.rs | 4 ++-- src/tools/clippy/clippy_utils/src/ty.rs | 10 +++++----- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 1f3cb4a61b895..a6d9676dd84ad 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,7 +1,7 @@ use rustc_hir as hir; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits; -use rustc_middle::ty::{self, Upcast}; +use rustc_middle::ty::{self, TypingMode, Upcast}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -38,7 +38,7 @@ pub(crate) fn synthesize_blanket_impls( if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { continue; } - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id); let impl_ty = ty.instantiate(tcx, args); let param_env = ty::ParamEnv::empty(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ea349f878e0ef..87b629078ff8e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -45,7 +45,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir_analysis::lower_ty; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; -use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_span::ExpnKind; use rustc_span::hygiene::{AstPass, MacroKind}; @@ -1863,7 +1863,7 @@ fn normalize<'tcx>( use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; // Try to normalize `::T` to a type - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let normalized = infcx .at(&ObligationCause::dummy(), cx.param_env) .query_normalize(ty) @@ -2399,7 +2399,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>( use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let kind = match variant.ctor_kind() { Some(CtorKind::Const) => VariantKind::CLike, Some(CtorKind::Fn) => VariantKind::Tuple( diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8e8e5c6ade8cb..47c21d89177bf 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -20,8 +20,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_metadata::creader::{CStore, LoadedMacro}; -use rustc_middle::ty; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_span::symbol::kw; use rustc_span::{Symbol, sym}; use rustc_target::spec::abi::Abi; @@ -613,7 +612,7 @@ fn generate_item_def_id_path( // No need to try to infer the actual parent item if it's not an associated item from the `impl` // block. if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); def_id = infcx .at(&ObligationCause::dummy(), tcx.param_env(def_id)) .query_normalize(ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity())) diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index cabc659225828..6ca599ed36113 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -9,7 +9,8 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ - self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults, + self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, + TypeckResults, }; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -203,7 +204,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc // 'cuz currently nothing changes after deleting this check. local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr) }) { - match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait( + match cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().type_implements_fn_trait( cx.param_env, Binder::bind_with_vars(callee_ty_adjusted, List::empty()), ty::PredicatePolarity::Positive, diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index cfd11e9339fb7..c74ba088b78e6 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -117,7 +117,7 @@ fn check_needless_must_use( } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) { // Ignore async functions unless Future::Output type is a must_use type if sig.header.is_async() { - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id)) && !is_must_use_ty(cx, future_ty) { diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index a4dbe134f3650..cf08c16458bd5 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if is_future { let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let cause = traits::ObligationCause::misc(span, fn_def_id); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index cfa1fdb81372f..82549413fa918 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -568,7 +568,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); !cx.tcx .infer_ctxt() - .build() + .build(cx.typing_mode()) .predicate_must_hold_modulo_regions(&obligation) }) { return false; diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index f6db12ed84e86..f7fa31d83aa4a 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -278,7 +278,7 @@ fn needless_borrow_count<'tcx>( let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty[..]); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); infcx.predicate_must_hold_modulo_regions(&obligation) }) }; diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 392cfcb813e85..2e5195d459f4d 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -160,7 +160,7 @@ impl NoEffect { // Remove `impl Future` to get `T` if cx.tcx.ty_is_opaque_future(ret_ty) && let Some(true_ret_ty) = - cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty) + cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().get_impl_future_output_ty(ret_ty) { ret_ty = true_ret_ty; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index f5fcf521b96cc..a548c6ef3b1fd 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -695,7 +695,7 @@ fn matches_preds<'tcx>( ty: Ty<'tcx>, preds: &'tcx [ty::PolyExistentialPredicate<'tcx>], ) -> bool { - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); preds .iter() .all(|&p| match cx.tcx.instantiate_bound_regions_with_erased(p) { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index ec3a693d2efec..3b05abc546f47 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -114,7 +114,7 @@ fn into_iter_bound<'tcx>( if !cx .tcx .infer_ctxt() - .build() + .build(cx.typing_mode()) .predicate_must_hold_modulo_regions(&obligation) { return None; diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 46739862de6b2..dbadc8432f630 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause}; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt, TypingMode}; use rustc_span::Span; use rustc_span::symbol::sym; use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; @@ -420,7 +420,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]), ); - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(obligation.param_env)); let mut selcx = SelectionContext::new(&infcx); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { return false; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 07c3d0eada005..c618bfe4488c1 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, TypingMode, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -268,7 +268,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(); + let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let args = args .into_iter() .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) @@ -362,7 +362,7 @@ fn is_normalizable_helper<'tcx>( } // prevent recursive loops, false-negative is better than endless loop leading to stack overflow cache.insert(ty, false); - let infcx = cx.tcx.infer_ctxt().build(); + let infcx = cx.tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let cause = ObligationCause::dummy(); let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() { match ty.kind() { @@ -1268,7 +1268,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( let cause = ObligationCause::dummy(); match tcx .infer_ctxt() - .build() + .build(TypingMode::from_param_env(param_env)) .at(&cause, param_env) .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { @@ -1284,7 +1284,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let cause = ObligationCause::dummy(); - match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) { + match tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)).at(&cause, param_env).query_normalize(ty) { Ok(ty) => ty.value, Err(_) => ty, } From 524a22e79057f2db0053bd002262fa88ea1a9947 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 29 Oct 2024 17:07:32 +0100 Subject: [PATCH 07/13] rebase --- compiler/rustc_trait_selection/src/traits/effects.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index bd8c04b765570..60b3357810a65 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -1,8 +1,9 @@ use rustc_hir as hir; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt}; use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation}; +use rustc_middle::span_bug; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::{span_bug, ty}; +use rustc_middle::ty::{self, TypingMode}; use rustc_type_ir::solve::NoSolution; use thin_vec::ThinVec; @@ -19,7 +20,7 @@ pub fn evaluate_host_effect_obligation<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, ) -> Result>, EvaluationFailure> { - if selcx.infcx.intercrate { + if matches!(selcx.infcx.typing_mode(obligation.param_env), TypingMode::Coherence) { span_bug!( obligation.cause.span, "should not select host obligation in old solver in intercrate mode" From 0783af89cdda89bf722ce157462821293d5c9a54 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Tue, 29 Oct 2024 18:29:39 +0000 Subject: [PATCH 08/13] Point to Fuchsia team in platform support docs --- src/doc/rustc/src/platform-support/fuchsia.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 0622f4dd564de..489f46e1cb98d 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -7,17 +7,9 @@ updatable, and performant. ## Target maintainers -The [Fuchsia team]: +See [`fuchsia.toml`] in the `team` repository for current target maintainers. -- Tyler Mandry ([@tmandry](https://github.com/tmandry)) -- David Koloski ([@djkoloski](https://github.com/djkoloski)) -- Julia Ryan ([@P1n3appl3](https://github.com/P1n3appl3)) -- Erick Tryzelaar ([@erickt](https://github.com/erickt)) - -As the team evolves over time, the specific members listed here may differ from -the members reported by the API. The API should be considered to be -authoritative if this occurs. Instead of pinging individual members, use -`@rustbot ping fuchsia` to contact the team on GitHub. +[`fuchsia.toml`]: https://github.com/rust-lang/team/blob/master/teams/fuchsia.toml ## Table of contents From 4a2e08af22ee97e97b21a1cd75d80a1a2f746a3e Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Wed, 21 Aug 2024 23:29:51 -0400 Subject: [PATCH 09/13] Don't lint `irrefutable_let_patterns` on leading patterns if `else if` let-chains. --- .../src/thir/pattern/check_match.rs | 25 +++++++++++++------ .../irrefutable-lets.disallowed.stderr | 20 ++++++++++++++- .../irrefutable-lets.rs | 20 +++++++++++++++ 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index bc1acd51c6911..a8ca19b788785 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -79,6 +79,8 @@ enum LetSource { IfLetGuard, LetElse, WhileLet, + Else, + ElseIfLet, } struct MatchVisitor<'p, 'tcx> { @@ -129,15 +131,20 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { // Give a specific `let_source` for the condition. let let_source = match ex.span.desugaring_kind() { Some(DesugaringKind::WhileLoop) => LetSource::WhileLet, - _ => LetSource::IfLet, + _ => match self.let_source { + LetSource::Else => LetSource::ElseIfLet, + _ => LetSource::IfLet, + }, }; self.with_let_source(let_source, |this| this.visit_expr(&self.thir[cond])); self.with_let_source(LetSource::None, |this| { this.visit_expr(&this.thir[then]); - if let Some(else_) = else_opt { - this.visit_expr(&this.thir[else_]); - } }); + if let Some(else_) = else_opt { + self.with_let_source(LetSource::Else, |this| { + this.visit_expr(&this.thir[else_]) + }); + } return; } ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { @@ -569,9 +576,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // and we shouldn't lint. // For let guards inside a match, prefixes might use bindings of the match pattern, // so can't always be moved out. + // For `else if let`, an extra indentation level would be required to move the bindings. // FIXME: Add checking whether the bindings are actually used in the prefix, // and lint if they are not. - if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) { + if !matches!( + self.let_source, + LetSource::WhileLet | LetSource::IfLetGuard | LetSource::ElseIfLet + ) { // Emit the lint let prefix = &chain_refutabilities[..until]; let span_start = prefix[0].unwrap().0; @@ -902,8 +913,8 @@ fn report_irrefutable_let_patterns( } match source { - LetSource::None | LetSource::PlainLet => bug!(), - LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), + LetSource::None | LetSource::PlainLet | LetSource::Else => bug!(), + LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr index be4a523155825..130d0296c5ece 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr @@ -111,5 +111,23 @@ LL | while let Some(ref first) = opt && let second = first && let _third = s = note: these patterns will always match = help: consider moving them into the body -error: aborting due to 12 previous errors +error: trailing irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:87:12 + | +LL | && let x = &opt + | ^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it into the body + +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:93:12 + | +LL | if let x = opt.clone().map(|_| 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct + +error: aborting due to 14 previous errors diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs index bd4df337614a0..e7d69f89773ee 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs @@ -75,4 +75,24 @@ fn main() { && let Range { start: local_start, end: _ } = first && let None = local_start { } + + // No error. An extra nesting level would be required for the `else if`. + if opt == Some(None..None) { + } else if let x = opt.clone().map(|_| 1) + && x == Some(1) + {} + + if opt == Some(None..None) { + } else if opt.is_some() + && let x = &opt + //[disallowed]~^ ERROR trailing irrefutable pattern in let chain + {} + + if opt == Some(None..None) { + } else { + if let x = opt.clone().map(|_| 1) + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + && x == Some(1) + {} + } } From e54c177118a5150b819c8a84054504ab8e1e7748 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Oct 2024 08:45:46 +1100 Subject: [PATCH 10/13] Remove `Analysis::into_engine`. This is a standard pattern: ``` MyAnalysis.into_engine(tcx, body).iterate_to_fixpoint() ``` `into_engine` and `iterate_to_fixpoint` are always called in pairs, but sometimes with a builder-style `pass_name` call between them. But a builder-style interface is overkill here. This has been bugging me a for a while. This commit: - Merges `Engine::new` and `Engine::iterate_to_fixpoint`. This removes the need for `Engine` to have fields, leaving it as a trivial type that the next commit will remove. - Renames `Analysis::into_engine` as `Analysis::iterate_to_fixpoint`, gives it an extra argument for the optional pass name, and makes it call `Engine::iterate_to_fixpoint` instead of `Engine::new`. This turns the pattern from above into this: ``` MyAnalysis.iterate_to_fixpoint(tcx, body, None) ``` which is shorter at every call site, and there's less plumbing required to support it. --- compiler/rustc_borrowck/src/lib.rs | 31 ++++++------ .../src/check_consts/check.rs | 12 ++--- .../src/framework/engine.rs | 47 +++++-------------- .../rustc_mir_dataflow/src/framework/mod.rs | 33 +++++++------ compiler/rustc_mir_dataflow/src/rustc_peek.rs | 15 +++--- compiler/rustc_mir_transform/src/coroutine.rs | 15 ++---- .../src/dataflow_const_prop.rs | 2 +- .../src/dead_store_elimination.rs | 3 +- compiler/rustc_mir_transform/src/dest_prop.rs | 5 +- .../src/elaborate_drops.rs | 8 +--- compiler/rustc_mir_transform/src/lint.rs | 6 +-- compiler/rustc_mir_transform/src/ref_prop.rs | 3 +- .../src/remove_uninit_drops.rs | 4 +- .../clippy_utils/src/mir/possible_borrower.rs | 4 +- 14 files changed, 72 insertions(+), 116 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 698fdafc93616..3e43d28eb5c99 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -193,9 +193,7 @@ fn do_mir_borrowck<'tcx>( .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true))); let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .pass_name("borrowck") - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, Some("borrowck")) .into_results_cursor(body); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure(); @@ -243,18 +241,21 @@ fn do_mir_borrowck<'tcx>( // usage significantly on some benchmarks. drop(flow_inits); - let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set) - .into_engine(tcx, body) - .pass_name("borrowck") - .iterate_to_fixpoint(); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .pass_name("borrowck") - .iterate_to_fixpoint(); - let flow_ever_inits = EverInitializedPlaces::new(body, &move_data) - .into_engine(tcx, body) - .pass_name("borrowck") - .iterate_to_fixpoint(); + let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); let movable_coroutine = // The first argument is the coroutine type passed by value diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 463a66d4e2e46..4d6f6715b9de3 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -63,8 +63,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, .. } = *ccx; FlowSensitiveAnalysis::new(NeedsDrop, ccx) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body) }); @@ -93,8 +92,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, .. } = *ccx; FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body) }); @@ -123,8 +121,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, .. } = *ccx; FlowSensitiveAnalysis::new(HasMutInterior, ccx) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body) }); @@ -239,8 +236,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { let always_live_locals = &always_storage_live_locals(&ccx.body); let mut maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) - .into_engine(ccx.tcx, &ccx.body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(ccx.tcx, &ccx.body, None) .into_results_cursor(&ccx.body); // And then check all `Return` in the MIR, and if a local is "maybe live" at a diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index cbd1083d037d2..44fda84ce03ef 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -71,25 +71,21 @@ where } /// A solver for dataflow problems. -pub struct Engine<'mir, 'tcx, A> -where - A: Analysis<'tcx>, -{ - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - entry_sets: IndexVec, - pass_name: Option<&'static str>, - analysis: A, -} +pub struct Engine; -impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A> -where - A: Analysis<'tcx, Domain = D>, - D: Clone + JoinSemiLattice, -{ +impl Engine { /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer /// function. - pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { + pub(crate) fn iterate_to_fixpoint<'mir, 'tcx, A>( + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + mut analysis: A, + pass_name: Option<&'static str>, + ) -> Results<'tcx, A> + where + A: Analysis<'tcx>, + A::Domain: DebugWithContext + Clone + JoinSemiLattice, + { let mut entry_sets = IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len()); analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); @@ -99,25 +95,6 @@ where bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); } - Engine { analysis, tcx, body, pass_name: None, entry_sets } - } - - /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis. - /// - /// Some analyses are run multiple times in the compilation pipeline. Give them a `pass_name` - /// to differentiate them. Otherwise, only the results for the latest run will be saved. - pub fn pass_name(mut self, name: &'static str) -> Self { - self.pass_name = Some(name); - self - } - - /// Computes the fixpoint for this dataflow problem and returns it. - pub fn iterate_to_fixpoint(self) -> Results<'tcx, A> - where - A::Domain: DebugWithContext, - { - let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self; - let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); if A::Direction::IS_FORWARD { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 959f1ea534090..5ad05921b4fd1 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -7,18 +7,17 @@ //! //! The `impls` module contains several examples of dataflow analyses. //! -//! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait, -//! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the -//! fixpoint solution to your dataflow problem, or implement the `ResultsVisitor` interface and use -//! `visit_results`. The following example uses the `ResultsCursor` approach. +//! Then call `iterate_to_fixpoint` on your type that impls `Analysis` to get a `Results`. From +//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem, +//! or implement the `ResultsVisitor` interface and use `visit_results`. The following example uses +//! the `ResultsCursor` approach. //! //! ```ignore (cross-crate-imports) -//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available. +//! use rustc_const_eval::dataflow::Analysis; // Makes `iterate_to_fixpoint` available. //! //! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { //! let analysis = MyAnalysis::new() -//! .into_engine(tcx, body) -//! .iterate_to_fixpoint() +//! .iterate_to_fixpoint(tcx, body, None) //! .into_results_cursor(body); //! //! // Print the dataflow state *after* each statement in the start block. @@ -39,6 +38,8 @@ use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; use rustc_middle::ty::TyCtxt; +use super::fmt::DebugWithContext; + mod cursor; mod direction; mod engine; @@ -223,26 +224,30 @@ pub trait Analysis<'tcx> { /* Extension methods */ - /// Creates an `Engine` to find the fixpoint for this dataflow problem. + /// Finds the fixpoint for this dataflow problem. /// /// You shouldn't need to override this. Its purpose is to enable method chaining like so: /// /// ```ignore (cross-crate-imports) /// let results = MyAnalysis::new(tcx, body) - /// .into_engine(tcx, body, def_id) - /// .iterate_to_fixpoint() + /// .iterate_to_fixpoint(tcx, body, None) /// .into_results_cursor(body); /// ``` - #[inline] - fn into_engine<'mir>( + /// You can optionally add a `pass_name` to the graphviz output for this particular run of a + /// dataflow analysis. Some analyses are run multiple times in the compilation pipeline. + /// Without a `pass_name` to differentiates them, only the results for the latest run will be + /// saved. + fn iterate_to_fixpoint<'mir>( self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, - ) -> Engine<'mir, 'tcx, Self> + pass_name: Option<&'static str>, + ) -> Results<'tcx, Self> where Self: Sized, + Self::Domain: DebugWithContext, { - Engine::new(tcx, body, self) + Engine::iterate_to_fixpoint(tcx, body, self, pass_name) } } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 5727517bd612a..99d0ccde1052c 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -43,31 +43,28 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let move_data = MoveData::gather_moves(body, tcx, |_| true); if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + let flow_inits = + MaybeInitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(tcx, body, None); sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + .iterate_to_fixpoint(tcx, body, None); sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + let flow_def_inits = + DefinitelyInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(tcx, body, None); sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body)); } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); + let flow_liveness = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None); sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 0a413d68020dc..859b257174ab0 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -666,14 +666,13 @@ fn locals_live_across_suspend_points<'tcx>( // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); // Calculate the MIR locals which have been previously // borrowed (even if they are still active). let borrowed_locals_results = - MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint(); + MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")); let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body); @@ -681,16 +680,12 @@ fn locals_live_across_suspend_points<'tcx>( // for. let mut requires_storage_cursor = MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); // Calculate the liveness of MIR locals ignoring borrows. - let mut liveness = MaybeLiveLocals - .into_engine(tcx, body) - .pass_name("coroutine") - .iterate_to_fixpoint() - .into_results_cursor(body); + let mut liveness = + MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body); let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); let mut live_locals_at_suspension_points = Vec::new(); diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 002216f50f2d1..07263460733cf 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { // Perform the actual dataflow analysis. let analysis = ConstAnalysis::new(tcx, body, map); let mut results = debug_span!("analyze") - .in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint()); + .in_scope(|| analysis.wrap().iterate_to_fixpoint(tcx, body, None)); // Collect results and patch the body afterwards. let mut visitor = Collector::new(tcx, &body.local_decls); diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index edffe6ce78f67..2898f82e25c38 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -37,8 +37,7 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { always_live.union(&borrowed_locals); let mut live = MaybeTransitiveLiveLocals::new(&always_live) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); // For blocks with a call terminator, if an argument copy can be turned into a move, diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index ad83c0295baec..beeab0d4a666b 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -169,10 +169,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body); - let live = MaybeLiveLocals - .into_engine(tcx, body) - .pass_name("MaybeLiveLocals-DestinationPropagation") - .iterate_to_fixpoint(); + let live = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("MaybeLiveLocals-DestProp")); let points = DenseLocationMap::new(body); let mut live = save_as_intervals(&points, body, live); diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 30e1ac05e039c..58e1db194380f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -64,18 +64,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data) .skipping_unreachable_unwind() - .into_engine(tcx, body) - .pass_name("elaborate_drops") - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, Some("elaborate_drops")) .into_results_cursor(body); let dead_unwinds = compute_dead_unwinds(body, &mut inits); let uninits = MaybeUninitializedPlaces::new(tcx, body, &env.move_data) .mark_inactive_variants_as_uninit() .skipping_unreachable_unwind(dead_unwinds) - .into_engine(tcx, body) - .pass_name("elaborate_drops") - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, Some("elaborate_drops")) .into_results_cursor(body); let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths); diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 23733994a8b4a..d8ff1cfc90b58 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -17,13 +17,11 @@ pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String let always_live_locals = &always_storage_live_locals(body); let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals)) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); let mut lint = Lint { diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 53e53d9d5ba8b..b11b503e8d430 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -126,8 +126,7 @@ fn compute_replacement<'tcx>( // Compute `MaybeStorageDead` dataflow to check that we only replace when the pointee is // definitely live. let mut maybe_dead = MaybeStorageDead::new(Cow::Owned(always_live_locals)) - .into_engine(tcx, body) - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, None) .into_results_cursor(body); // Map for each local to the pointee. diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 09969a4c7cc7f..55dd96100b0a6 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -22,9 +22,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .pass_name("remove_uninit_drops") - .iterate_to_fixpoint() + .iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops")) .into_results_cursor(body); let mut to_remove = vec![]; diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index a00196c4b511d..6b3078f52aff5 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -185,9 +185,7 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { vis.into_map(cx) }; let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len()))) - .into_engine(cx.tcx, mir) - .pass_name("redundant_clone") - .iterate_to_fixpoint() + .iterate_to_fixpoint(cx.tcx, mir, Some("redundant_clone")) .into_results_cursor(mir); let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin); vis.visit_body(mir); From d78e7bbeff6006feef9c04140c1e6bf67bdbef00 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Oct 2024 09:34:37 +1100 Subject: [PATCH 11/13] Remove `Engine`. It's no longer needed. `Engine::iterate_to_fixpoint` can be inlined into `Analysis::iterate_to_fixpoint` and removed. The commit also renames `engine.rs` as `results.rs`. --- .../rustc_mir_dataflow/src/framework/mod.rs | 78 +++++++++++++-- .../src/framework/{engine.rs => results.rs} | 98 +------------------ compiler/rustc_mir_dataflow/src/lib.rs | 6 +- 3 files changed, 80 insertions(+), 102 deletions(-) rename compiler/rustc_mir_dataflow/src/framework/{engine.rs => results.rs} (66%) diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 5ad05921b4fd1..8f81da8bb0499 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -33,25 +33,29 @@ use std::cmp::Ordering; -use rustc_index::Idx; +use rustc_data_structures::work_queue::WorkQueue; use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; -use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; +use rustc_index::{Idx, IndexVec}; +use rustc_middle::bug; +use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal}; use rustc_middle::ty::TyCtxt; +use tracing::error; +use self::results::write_graphviz_results; use super::fmt::DebugWithContext; mod cursor; mod direction; -mod engine; pub mod fmt; pub mod graphviz; pub mod lattice; +mod results; mod visitor; pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; -pub use self::engine::{Engine, Results}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; +pub use self::results::Results; pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds @@ -238,7 +242,7 @@ pub trait Analysis<'tcx> { /// Without a `pass_name` to differentiates them, only the results for the latest run will be /// saved. fn iterate_to_fixpoint<'mir>( - self, + mut self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, pass_name: Option<&'static str>, @@ -247,7 +251,69 @@ pub trait Analysis<'tcx> { Self: Sized, Self::Domain: DebugWithContext, { - Engine::iterate_to_fixpoint(tcx, body, self, pass_name) + let mut entry_sets = + IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len()); + self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); + + if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) { + bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); + } + + let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); + + if Self::Direction::IS_FORWARD { + for (bb, _) in traversal::reverse_postorder(body) { + dirty_queue.insert(bb); + } + } else { + // Reverse post-order on the reverse CFG may generate a better iteration order for + // backward dataflow analyses, but probably not enough to matter. + for (bb, _) in traversal::postorder(body) { + dirty_queue.insert(bb); + } + } + + // `state` is not actually used between iterations; + // this is just an optimization to avoid reallocating + // every iteration. + let mut state = self.bottom_value(body); + while let Some(bb) = dirty_queue.pop() { + let bb_data = &body[bb]; + + // Set the state to the entry state of the block. + // This is equivalent to `state = entry_sets[bb].clone()`, + // but it saves an allocation, thus improving compile times. + state.clone_from(&entry_sets[bb]); + + // Apply the block transfer function, using the cached one if it exists. + let edges = Self::Direction::apply_effects_in_block(&mut self, &mut state, bb, bb_data); + + Self::Direction::join_state_into_successors_of( + &mut self, + body, + &mut state, + bb, + edges, + |target: BasicBlock, state: &Self::Domain| { + let set_changed = entry_sets[target].join(state); + if set_changed { + dirty_queue.insert(target); + } + }, + ); + } + + let results = Results { analysis: self, entry_sets }; + + if tcx.sess.opts.unstable_opts.dump_mir_dataflow { + let (res, results) = write_graphviz_results(tcx, body, results, pass_name); + if let Err(e) = res { + error!("Failed to write graphviz dataflow results: {}", e); + } + results + } else { + results + } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs similarity index 66% rename from compiler/rustc_mir_dataflow/src/framework/engine.rs rename to compiler/rustc_mir_dataflow/src/framework/results.rs index 44fda84ce03ef..366fcbf33ba3c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -1,23 +1,19 @@ -//! A solver for dataflow problems. +//! Dataflow analysis results. use std::ffi::OsString; use std::path::PathBuf; -use rustc_data_structures::work_queue::WorkQueue; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; -use rustc_middle::bug; use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal}; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_span::symbol::{Symbol, sym}; -use tracing::{debug, error}; +use tracing::debug; use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::DebugWithContext; -use super::{ - Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results, -}; +use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results}; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; @@ -65,101 +61,17 @@ where body: &'mir mir::Body<'tcx>, vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, ) { - let blocks = mir::traversal::reachable(body); + let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) } } -/// A solver for dataflow problems. -pub struct Engine; - -impl Engine { - /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer - /// function. - pub(crate) fn iterate_to_fixpoint<'mir, 'tcx, A>( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - mut analysis: A, - pass_name: Option<&'static str>, - ) -> Results<'tcx, A> - where - A: Analysis<'tcx>, - A::Domain: DebugWithContext + Clone + JoinSemiLattice, - { - let mut entry_sets = - IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len()); - analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); - - if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != analysis.bottom_value(body) - { - bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); - } - - let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); - - if A::Direction::IS_FORWARD { - for (bb, _) in traversal::reverse_postorder(body) { - dirty_queue.insert(bb); - } - } else { - // Reverse post-order on the reverse CFG may generate a better iteration order for - // backward dataflow analyses, but probably not enough to matter. - for (bb, _) in traversal::postorder(body) { - dirty_queue.insert(bb); - } - } - - // `state` is not actually used between iterations; - // this is just an optimization to avoid reallocating - // every iteration. - let mut state = analysis.bottom_value(body); - while let Some(bb) = dirty_queue.pop() { - let bb_data = &body[bb]; - - // Set the state to the entry state of the block. - // This is equivalent to `state = entry_sets[bb].clone()`, - // but it saves an allocation, thus improving compile times. - state.clone_from(&entry_sets[bb]); - - // Apply the block transfer function, using the cached one if it exists. - let edges = - A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data); - - A::Direction::join_state_into_successors_of( - &mut analysis, - body, - &mut state, - bb, - edges, - |target: BasicBlock, state: &A::Domain| { - let set_changed = entry_sets[target].join(state); - if set_changed { - dirty_queue.insert(target); - } - }, - ); - } - - let results = Results { analysis, entry_sets }; - - if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let (res, results) = write_graphviz_results(tcx, body, results, pass_name); - if let Err(e) = res { - error!("Failed to write graphviz dataflow results: {}", e); - } - results - } else { - results - } - } -} - // Graphviz /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are /// the same. -fn write_graphviz_results<'tcx, A>( +pub(super) fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, results: Results<'tcx, A>, diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b284f0308f979..b404e3bfb72c3 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable, - Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, - lattice, visit_results, + Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results, + ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, + visit_results, }; use self::move_paths::MoveData; From 65ff2a6ad71de45c848a622d86b6c74092e1b734 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 30 Oct 2024 10:02:46 +1100 Subject: [PATCH 12/13] Consistently use safe wrapper function `set_section` --- compiler/rustc_codegen_llvm/src/back/lto.rs | 3 ++- compiler/rustc_codegen_llvm/src/back/write.rs | 16 +++++++--------- compiler/rustc_codegen_llvm/src/base.rs | 6 ++---- compiler/rustc_codegen_llvm/src/context.rs | 2 +- compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 6 ++++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 02149e176eabe..48beb9be2b2a1 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -165,13 +165,14 @@ fn get_bitcode_slice_from_object_data<'a>( // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment // name" which in the public API for sections gets treated as part of the section name, but // internally in MachOObjectFile.cpp gets treated separately. - let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,"); + let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,"); let mut len = 0; let data = unsafe { llvm::LLVMRustGetSliceFromObjectDataByName( obj.as_ptr(), obj.len(), section_name.as_ptr(), + section_name.len(), &mut len, ) }; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index e68ba96f14f91..bfa9e8b82a033 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1,4 +1,4 @@ -use std::ffi::CString; +use std::ffi::{CStr, CString}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -958,14 +958,13 @@ fn target_is_aix(cgcx: &CodegenContext) -> bool { cgcx.opts.target_triple.triple().contains("-aix") } -//FIXME use c string literals here too -pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static str { +pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { if target_is_apple(cgcx) { - "__LLVM,__bitcode\0" + c"__LLVM,__bitcode" } else if target_is_aix(cgcx) { - ".ipa\0" + c".ipa" } else { - ".llvmbc\0" + c".llvmbc" } } @@ -1042,8 +1041,7 @@ unsafe fn embed_bitcode( ); llvm::LLVMSetInitializer(llglobal, llconst); - let section = bitcode_section_name(cgcx); - llvm::LLVMSetSection(llglobal, section.as_c_char_ptr()); + llvm::set_section(llglobal, bitcode_section_name(cgcx)); llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); @@ -1061,7 +1059,7 @@ unsafe fn embed_bitcode( } else { c".llvmcmd" }; - llvm::LLVMSetSection(llglobal, section.as_ptr()); + llvm::set_section(llglobal, section); llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); } else { // We need custom section flags, so emit module-level inline assembly. diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 0ba8d82406a82..3279389479499 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -145,10 +145,8 @@ pub(crate) fn compile_codegen_unit( pub(crate) fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { let Some(sect) = attrs.link_section else { return }; - unsafe { - let buf = SmallCStr::new(sect.as_str()); - llvm::LLVMSetSection(llval, buf.as_ptr()); - } + let buf = SmallCStr::new(sect.as_str()); + llvm::set_section(llval, &buf); } pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index f33da42d63e87..9778ff4918c0d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -565,7 +565,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); llvm::set_linkage(g, llvm::Linkage::AppendingLinkage); - llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr()); + llvm::set_section(g, c"llvm.metadata"); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 7947c9c8c8efd..aef8642f1998a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -72,7 +72,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( let section_var = cx .define_global(section_var_name, llvm_type) .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); - llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr()); + llvm::set_section(section_var, c".debug_gdb_scripts"); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 888d41d472668..c0ca7e5102509 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2416,6 +2416,7 @@ unsafe extern "C" { data: *const u8, len: usize, name: *const u8, + name_len: usize, out_len: &mut usize, ) -> *const u8; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 20bf32d731e12..3e906f89c15c3 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1559,8 +1559,10 @@ extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context, extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, size_t len, const char *name, + size_t name_len, size_t *out_len) { *out_len = 0; + auto Name = StringRef(name, name_len); auto Data = StringRef(data, len); auto Buffer = MemoryBufferRef(Data, ""); // The id is unused. file_magic Type = identify_magic(Buffer.getBuffer()); @@ -1571,8 +1573,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, return nullptr; } for (const object::SectionRef &Sec : (*ObjFileOrError)->sections()) { - Expected Name = Sec.getName(); - if (Name && *Name == name) { + Expected SecName = Sec.getName(); + if (SecName && *SecName == Name) { Expected SectionOrError = Sec.getContents(); if (!SectionOrError) { LLVMRustSetLastError(toString(SectionOrError.takeError()).c_str()); From c3071590ab70f016380fe16030057e84b76e59eb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 28 Oct 2024 17:25:40 +1100 Subject: [PATCH 13/13] Clean up FFI calls for operand bundles --- compiler/rustc_codegen_llvm/src/allocator.rs | 3 +- compiler/rustc_codegen_llvm/src/builder.rs | 23 ++--- compiler/rustc_codegen_llvm/src/common.rs | 8 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 91 ++++++++++--------- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 38 +++++--- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 78 +++------------- 6 files changed, 103 insertions(+), 138 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index a2e6c7eb85619..149ded28356b8 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -154,7 +154,7 @@ fn create_wrapper_function( .enumerate() .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint)) .collect::>(); - let ret = llvm::LLVMRustBuildCall( + let ret = llvm::LLVMBuildCallWithOperandBundles( llbuilder, ty, callee, @@ -162,6 +162,7 @@ fn create_wrapper_function( args.len() as c_uint, [].as_ptr(), 0 as c_uint, + c"".as_ptr(), ); llvm::LLVMSetTailCall(ret, True); if output.is_some() { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8702532c36eee..f8eb3e0c982ca 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -239,7 +239,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let args = self.check_call("invoke", llty, llfn, args); let funclet_bundle = funclet.map(|funclet| funclet.bundle()); - let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw); let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); if let Some(funclet_bundle) = funclet_bundle { bundles.push(funclet_bundle); @@ -250,13 +249,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw); - if let Some(kcfi_bundle) = kcfi_bundle { + if let Some(kcfi_bundle) = kcfi_bundle.as_deref() { bundles.push(kcfi_bundle); } let invoke = unsafe { - llvm::LLVMRustBuildInvoke( + llvm::LLVMBuildInvokeWithOperandBundles( self.llbuilder, llty, llfn, @@ -1179,7 +1177,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let args = self.check_call("call", llty, llfn, args); let funclet_bundle = funclet.map(|funclet| funclet.bundle()); - let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw); let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); if let Some(funclet_bundle) = funclet_bundle { bundles.push(funclet_bundle); @@ -1190,13 +1187,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw); - if let Some(kcfi_bundle) = kcfi_bundle { + if let Some(kcfi_bundle) = kcfi_bundle.as_deref() { bundles.push(kcfi_bundle); } let call = unsafe { - llvm::LLVMRustBuildCall( + llvm::LLVMBuildCallWithOperandBundles( self.llbuilder, llty, llfn, @@ -1204,6 +1200,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { args.len() as c_uint, bundles.as_ptr(), bundles.len() as c_uint, + c"".as_ptr(), ) }; if let Some(fn_abi) = fn_abi { @@ -1509,7 +1506,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let args = self.check_call("callbr", llty, llfn, args); let funclet_bundle = funclet.map(|funclet| funclet.bundle()); - let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw); let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); if let Some(funclet_bundle) = funclet_bundle { bundles.push(funclet_bundle); @@ -1520,13 +1516,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw); - if let Some(kcfi_bundle) = kcfi_bundle { + if let Some(kcfi_bundle) = kcfi_bundle.as_deref() { bundles.push(kcfi_bundle); } let callbr = unsafe { - llvm::LLVMRustBuildCallBr( + llvm::LLVMBuildCallBr( self.llbuilder, llty, llfn, @@ -1601,7 +1596,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, instance: Option>, llfn: &'ll Value, - ) -> Option> { + ) -> Option> { let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) }; let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled() && let Some(fn_abi) = fn_abi @@ -1627,7 +1622,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) }; - Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)])) + Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)])) } else { None }; diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 29adc616ee204..8852dec7d9ff1 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -17,7 +17,7 @@ use tracing::debug; use crate::consts::const_alloc_to_llvm; pub(crate) use crate::context::CodegenCx; -use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, OperandBundleDef, True}; +use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True}; use crate::type_::Type; use crate::value::Value; @@ -63,19 +63,19 @@ use crate::value::Value; /// the `OperandBundleDef` value created for MSVC landing pads. pub(crate) struct Funclet<'ll> { cleanuppad: &'ll Value, - operand: OperandBundleDef<'ll>, + operand: llvm::OperandBundleOwned<'ll>, } impl<'ll> Funclet<'ll> { pub(crate) fn new(cleanuppad: &'ll Value) -> Self { - Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) } + Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) } } pub(crate) fn cleanuppad(&self) -> &'ll Value { self.cleanuppad } - pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> { + pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> { &self.operand } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 888d41d472668..d67f76b51a237 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::marker::PhantomData; +use std::ptr; use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t}; use rustc_macros::TryFromU32; @@ -708,8 +709,9 @@ unsafe extern "C" { } #[repr(C)] pub struct RustArchiveMember<'a>(InvariantOpaque<'a>); +/// Opaque pointee of `LLVMOperandBundleRef`. #[repr(C)] -pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); +pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct Linker<'a>(InvariantOpaque<'a>); @@ -1538,6 +1540,50 @@ unsafe extern "C" { pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat; pub fn LLVMSetComdat(V: &Value, C: &Comdat); + + pub(crate) fn LLVMCreateOperandBundle( + Tag: *const c_char, + TagLen: size_t, + Args: *const &'_ Value, + NumArgs: c_uint, + ) -> *mut OperandBundle<'_>; + pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull>); + + pub(crate) fn LLVMBuildCallWithOperandBundles<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Bundles: *const &OperandBundle<'a>, + NumBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; + pub(crate) fn LLVMBuildInvokeWithOperandBundles<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Then: &'a BasicBlock, + Catch: &'a BasicBlock, + Bundles: *const &OperandBundle<'a>, + NumBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; + pub(crate) fn LLVMBuildCallBr<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + DefaultDest: &'a BasicBlock, + IndirectDests: *const &'a BasicBlock, + NumIndirectDests: c_uint, + Args: *const &'a Value, + NumArgs: c_uint, + Bundles: *const &OperandBundle<'a>, + NumBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; } #[link(name = "llvm-wrapper", kind = "static")] @@ -1623,47 +1669,11 @@ unsafe extern "C" { AttrsLen: size_t, ); - pub fn LLVMRustBuildInvoke<'a>( - B: &Builder<'a>, - Ty: &'a Type, - Fn: &'a Value, - Args: *const &'a Value, - NumArgs: c_uint, - Then: &'a BasicBlock, - Catch: &'a BasicBlock, - OpBundles: *const &OperandBundleDef<'a>, - NumOpBundles: c_uint, - Name: *const c_char, - ) -> &'a Value; - - pub fn LLVMRustBuildCallBr<'a>( - B: &Builder<'a>, - Ty: &'a Type, - Fn: &'a Value, - DefaultDest: &'a BasicBlock, - IndirectDests: *const &'a BasicBlock, - NumIndirectDests: c_uint, - Args: *const &'a Value, - NumArgs: c_uint, - OpBundles: *const &OperandBundleDef<'a>, - NumOpBundles: c_uint, - Name: *const c_char, - ) -> &'a Value; - pub fn LLVMRustSetFastMath(Instr: &Value); pub fn LLVMRustSetAlgebraicMath(Instr: &Value); pub fn LLVMRustSetAllowReassoc(Instr: &Value); // Miscellaneous instructions - pub fn LLVMRustBuildCall<'a>( - B: &Builder<'a>, - Ty: &'a Type, - Fn: &'a Value, - Args: *const &'a Value, - NumArgs: c_uint, - OpBundles: *const &OperandBundleDef<'a>, - NumOpBundles: c_uint, - ) -> &'a Value; pub fn LLVMRustBuildMemCpy<'a>( B: &Builder<'a>, Dst: &'a Value, @@ -2357,13 +2367,6 @@ unsafe extern "C" { pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine); - pub fn LLVMRustBuildOperandBundleDef( - Name: *const c_char, - Inputs: *const &'_ Value, - NumInputs: c_uint, - ) -> &mut OperandBundleDef<'_>; - pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>); - pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); pub fn LLVMRustSetModulePICLevel(M: &Module); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index acd425bbb8e7b..00a5cd3b8595f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -2,11 +2,12 @@ use std::cell::RefCell; use std::ffi::{CStr, CString}; +use std::ops::Deref; +use std::ptr; use std::str::FromStr; use std::string::FromUtf8Error; use libc::c_uint; -use rustc_data_structures::small_c_str::SmallCStr; use rustc_llvm::RustString; use rustc_target::abi::{Align, Size, WrappingRange}; @@ -331,28 +332,43 @@ pub fn last_error() -> Option { } } -pub struct OperandBundleDef<'a> { - pub raw: &'a mut ffi::OperandBundleDef<'a>, +/// Owns an [`OperandBundle`], and will dispose of it when dropped. +pub(crate) struct OperandBundleOwned<'a> { + raw: ptr::NonNull>, } -impl<'a> OperandBundleDef<'a> { - pub fn new(name: &str, vals: &[&'a Value]) -> Self { - let name = SmallCStr::new(name); - let def = unsafe { - LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) +impl<'a> OperandBundleOwned<'a> { + pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self { + let raw = unsafe { + LLVMCreateOperandBundle( + name.as_c_char_ptr(), + name.len(), + vals.as_ptr(), + vals.len() as c_uint, + ) }; - OperandBundleDef { raw: def } + OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() } } } -impl Drop for OperandBundleDef<'_> { +impl Drop for OperandBundleOwned<'_> { fn drop(&mut self) { unsafe { - LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); + LLVMDisposeOperandBundle(self.raw); } } } +impl<'a> Deref for OperandBundleOwned<'a> { + type Target = OperandBundle<'a>; + + fn deref(&self) -> &Self::Target { + // SAFETY: The returned reference is opaque and can only used for FFI. + // It is valid for as long as `&self` is. + unsafe { self.raw.as_ref() } + } +} + pub(crate) fn add_module_flag_u32( module: &Module, merge_behavior: ModuleFlagMergeBehavior, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index b3dab6d512e49..645b4082be5de 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1537,38 +1537,6 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, return true; } -extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, - LLVMValueRef *Inputs, - unsigned NumInputs) { - return new OperandBundleDef(Name, - ArrayRef(unwrap(Inputs), NumInputs)); -} - -extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { - delete Bundle; -} - -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). -extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, - LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, - OperandBundleDef **OpBundlesIndirect, - unsigned NumOpBundles) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = unwrap(Ty); - - // FIXME: Is there a way around this? - SmallVector OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); - } - - return wrap(unwrap(B)->CreateCall(FTy, Callee, - ArrayRef(unwrap(Args), NumArgs), - ArrayRef(OpBundles))); -} - extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, @@ -1596,37 +1564,18 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, MaybeAlign(DstAlign), IsVolatile)); } -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). -extern "C" LLVMValueRef -LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMValueRef *Args, unsigned NumArgs, - LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, - OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles, - const char *Name) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = unwrap(Ty); - - // FIXME: Is there a way around this? - SmallVector OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); - } - - return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), - ArrayRef(unwrap(Args), NumArgs), - ArrayRef(OpBundles), - Name)); -} +// Polyfill for `LLVMBuildCallBr`, which was added in LLVM 19. +// +// FIXME: Remove when Rust's minimum supported LLVM version reaches 19. +#if LLVM_VERSION_LT(19, 0) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef) -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). extern "C" LLVMValueRef -LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMBasicBlockRef DefaultDest, - LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests, - LLVMValueRef *Args, unsigned NumArgs, - OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles, - const char *Name) { +LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, LLVMBasicBlockRef *IndirectDests, + unsigned NumIndirectDests, LLVMValueRef *Args, unsigned NumArgs, + LLVMOperandBundleRef *Bundles, unsigned NumBundles, + const char *Name) { Value *Callee = unwrap(Fn); FunctionType *FTy = unwrap(Ty); @@ -1639,9 +1588,9 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, // FIXME: Is there a way around this? SmallVector OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); + OpBundles.reserve(NumBundles); + for (unsigned i = 0; i < NumBundles; ++i) { + OpBundles.push_back(*unwrap(Bundles[i])); } return wrap( @@ -1650,6 +1599,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, ArrayRef(unwrap(Args), NumArgs), ArrayRef(OpBundles), Name)); } +#endif extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) {