diff options
| author | bors <bors@rust-lang.org> | 2023-03-16 23:05:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-03-16 23:05:57 +0000 |
| commit | 3831a254905873af4da996ab21c6f9f3d4050051 (patch) | |
| tree | d82a4ce76a940fc631c0d2ef7e1cc6497e5746b6 /compiler | |
| parent | b024de1673487c3de0ce7dc4c3c9ec470746006a (diff) | |
| parent | ba1c09429e5ad091d524c975f1383d1992f7f17a (diff) | |
| download | rust-3831a254905873af4da996ab21c6f9f3d4050051.tar.gz rust-3831a254905873af4da996ab21c6f9f3d4050051.zip | |
Auto merge of #2817 - saethlin:rustup, r=saethlin
rustup Doing a sync just before I do a rustc-push
Diffstat (limited to 'compiler')
136 files changed, 2028 insertions, 1517 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6503bf2bab7..5d164bc4b3c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1184,6 +1184,15 @@ impl Expr { expr } + pub fn peel_parens_and_refs(&self) -> &Expr { + let mut expr = self; + while let ExprKind::Paren(inner) | ExprKind::AddrOf(BorrowKind::Ref, _, inner) = &expr.kind + { + expr = inner; + } + expr + } + /// Attempts to reparse as `Ty` (for diagnostic purposes). pub fn to_ty(&self) -> Option<P<Ty>> { let kind = match &self.kind { diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index d021bea5eca..356b9bb6371 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -131,8 +131,8 @@ impl FormatArguments { &self.arguments[..] } - pub fn all_args_mut(&mut self) -> &mut [FormatArgument] { - &mut self.arguments[..] + pub fn all_args_mut(&mut self) -> &mut Vec<FormatArgument> { + &mut self.arguments } } diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 4095e225a80..72352b138cb 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -7,13 +7,172 @@ use rustc_hir as hir; use rustc_span::{ sym, symbol::{kw, Ident}, - Span, + Span, Symbol, }; +use std::borrow::Cow; impl<'hir> LoweringContext<'_, 'hir> { pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> { - expand_format_args(self, sp, fmt) + // Never call the const constructor of `fmt::Arguments` if the + // format_args!() had any arguments _before_ flattening/inlining. + let allow_const = fmt.arguments.all_args().is_empty(); + let mut fmt = Cow::Borrowed(fmt); + if self.tcx.sess.opts.unstable_opts.flatten_format_args { + fmt = flatten_format_args(fmt); + fmt = inline_literals(fmt); + } + expand_format_args(self, sp, &fmt, allow_const) + } +} + +/// Flattens nested `format_args!()` into one. +/// +/// Turns +/// +/// `format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3)` +/// +/// into +/// +/// `format_args!("a {} b{}! {}.", 1, 2, 3)`. +fn flatten_format_args(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> { + let mut i = 0; + while i < fmt.template.len() { + if let FormatArgsPiece::Placeholder(placeholder) = &fmt.template[i] + && let FormatTrait::Display | FormatTrait::Debug = &placeholder.format_trait + && let Ok(arg_index) = placeholder.argument.index + && let arg = fmt.arguments.all_args()[arg_index].expr.peel_parens_and_refs() + && let ExprKind::FormatArgs(_) = &arg.kind + // Check that this argument is not used by any other placeholders. + && fmt.template.iter().enumerate().all(|(j, p)| + i == j || + !matches!(p, FormatArgsPiece::Placeholder(placeholder) + if placeholder.argument.index == Ok(arg_index)) + ) + { + // Now we need to mutate the outer FormatArgs. + // If this is the first time, this clones the outer FormatArgs. + let fmt = fmt.to_mut(); + + // Take the inner FormatArgs out of the outer arguments, and + // replace it by the inner arguments. (We can't just put those at + // the end, because we need to preserve the order of evaluation.) + + let args = fmt.arguments.all_args_mut(); + let remaining_args = args.split_off(arg_index + 1); + let old_arg_offset = args.len(); + let mut fmt2 = &mut args.pop().unwrap().expr; // The inner FormatArgs. + let fmt2 = loop { // Unwrap the Expr to get to the FormatArgs. + match &mut fmt2.kind { + ExprKind::Paren(inner) | ExprKind::AddrOf(BorrowKind::Ref, _, inner) => fmt2 = inner, + ExprKind::FormatArgs(fmt2) => break fmt2, + _ => unreachable!(), + } + }; + + args.append(fmt2.arguments.all_args_mut()); + let new_arg_offset = args.len(); + args.extend(remaining_args); + + // Correct the indexes that refer to the arguments after the newly inserted arguments. + for_all_argument_indexes(&mut fmt.template, |index| { + if *index >= old_arg_offset { + *index -= old_arg_offset; + *index += new_arg_offset; + } + }); + + // Now merge the placeholders: + + let rest = fmt.template.split_off(i + 1); + fmt.template.pop(); // remove the placeholder for the nested fmt args. + // Insert the pieces from the nested format args, but correct any + // placeholders to point to the correct argument index. + for_all_argument_indexes(&mut fmt2.template, |index| *index += arg_index); + fmt.template.append(&mut fmt2.template); + fmt.template.extend(rest); + + // Don't increment `i` here, so we recurse into the newly added pieces. + } else { + i += 1; + } } + fmt +} + +/// Inline literals into the format string. +/// +/// Turns +/// +/// `format_args!("Hello, {}! {} {}", "World", 123, x)` +/// +/// into +/// +/// `format_args!("Hello, World! 123 {}", x)`. +fn inline_literals(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> { + let mut was_inlined = vec![false; fmt.arguments.all_args().len()]; + let mut inlined_anything = false; + + for i in 0..fmt.template.len() { + let FormatArgsPiece::Placeholder(placeholder) = &fmt.template[i] else { continue }; + let Ok(arg_index) = placeholder.argument.index else { continue }; + + let mut literal = None; + + if let FormatTrait::Display = placeholder.format_trait + && placeholder.format_options == Default::default() + && let arg = fmt.arguments.all_args()[arg_index].expr.peel_parens_and_refs() + && let ExprKind::Lit(lit) = arg.kind + { + if let token::LitKind::Str | token::LitKind::StrRaw(_) = lit.kind + && let Ok(LitKind::Str(s, _)) = LitKind::from_token_lit(lit) + { + literal = Some(s); + } else if let token::LitKind::Integer = lit.kind + && let Ok(LitKind::Int(n, _)) = LitKind::from_token_lit(lit) + { + literal = Some(Symbol::intern(&n.to_string())); + } + } + + if let Some(literal) = literal { + // Now we need to mutate the outer FormatArgs. + // If this is the first time, this clones the outer FormatArgs. + let fmt = fmt.to_mut(); + // Replace the placeholder with the literal. + fmt.template[i] = FormatArgsPiece::Literal(literal); + was_inlined[arg_index] = true; + inlined_anything = true; + } + } + + // Remove the arguments that were inlined. + if inlined_anything { + let fmt = fmt.to_mut(); + + let mut remove = was_inlined; + + // Don't remove anything that's still used. + for_all_argument_indexes(&mut fmt.template, |index| remove[*index] = false); + + // Drop all the arguments that are marked for removal. + let mut remove_it = remove.iter(); + fmt.arguments.all_args_mut().retain(|_| remove_it.next() != Some(&true)); + + // Calculate the mapping of old to new indexes for the remaining arguments. + let index_map: Vec<usize> = remove + .into_iter() + .scan(0, |i, remove| { + let mapped = *i; + *i += !remove as usize; + Some(mapped) + }) + .collect(); + + // Correct the indexes that refer to arguments that have shifted position. + for_all_argument_indexes(&mut fmt.template, |index| *index = index_map[*index]); + } + + fmt } #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] @@ -189,11 +348,26 @@ fn expand_format_args<'hir>( ctx: &mut LoweringContext<'_, 'hir>, macsp: Span, fmt: &FormatArgs, + allow_const: bool, ) -> hir::ExprKind<'hir> { + let mut incomplete_lit = String::new(); let lit_pieces = ctx.arena.alloc_from_iter(fmt.template.iter().enumerate().filter_map(|(i, piece)| { match piece { - &FormatArgsPiece::Literal(s) => Some(ctx.expr_str(fmt.span, s)), + &FormatArgsPiece::Literal(s) => { + // Coalesce adjacent literal pieces. + if let Some(FormatArgsPiece::Literal(_)) = fmt.template.get(i + 1) { + incomplete_lit.push_str(s.as_str()); + None + } else if !incomplete_lit.is_empty() { + incomplete_lit.push_str(s.as_str()); + let s = Symbol::intern(&incomplete_lit); + incomplete_lit.clear(); + Some(ctx.expr_str(fmt.span, s)) + } else { + Some(ctx.expr_str(fmt.span, s)) + } + } &FormatArgsPiece::Placeholder(_) => { // Inject empty string before placeholders when not already preceded by a literal piece. if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) { @@ -244,6 +418,18 @@ fn expand_format_args<'hir>( let arguments = fmt.arguments.all_args(); + if allow_const && arguments.is_empty() && argmap.is_empty() { + // Generate: + // <core::fmt::Arguments>::new_const(lit_pieces) + let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + macsp, + hir::LangItem::FormatArguments, + sym::new_const, + )); + let new_args = ctx.arena.alloc_from_iter([lit_pieces]); + return hir::ExprKind::Call(new, new_args); + } + // If the args array contains exactly all the original arguments once, // in order, we can use a simple array instead of a `match` construction. // However, if there's a yield point in any argument except the first one, @@ -290,25 +476,14 @@ fn expand_format_args<'hir>( let args_ident = Ident::new(sym::args, macsp); let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| { - if let Some(arg) = arguments.get(arg_index) { - let sp = arg.expr.span.with_ctxt(macsp.ctxt()); - let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id); - let arg = ctx.arena.alloc(ctx.expr( - sp, - hir::ExprKind::Field( - args_ident_expr, - Ident::new(sym::integer(arg_index), macsp), - ), - )); - make_argument(ctx, sp, arg, ty) - } else { - ctx.expr( - macsp, - hir::ExprKind::Err( - ctx.tcx.sess.delay_span_bug(macsp, format!("no arg at {arg_index}")), - ), - ) - } + let arg = &arguments[arg_index]; + let sp = arg.expr.span.with_ctxt(macsp.ctxt()); + let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id); + let arg = ctx.arena.alloc(ctx.expr( + sp, + hir::ExprKind::Field(args_ident_expr, Ident::new(sym::integer(arg_index), macsp)), + )); + make_argument(ctx, sp, arg, ty) })); let elements: Vec<_> = arguments .iter() @@ -409,3 +584,22 @@ fn may_contain_yield_point(e: &ast::Expr) -> bool { visitor.visit_expr(e); visitor.0 } + +fn for_all_argument_indexes(template: &mut [FormatArgsPiece], mut f: impl FnMut(&mut usize)) { + for piece in template { + let FormatArgsPiece::Placeholder(placeholder) = piece else { continue }; + if let Ok(index) = &mut placeholder.argument.index { + f(index); + } + if let Some(FormatCount::Argument(FormatArgPosition { index: Ok(index), .. })) = + &mut placeholder.format_options.width + { + f(index); + } + if let Some(FormatCount::Argument(FormatArgPosition { index: Ok(index), .. })) = + &mut placeholder.format_options.precision + { + f(index); + } + } +} diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 0762987e229..2cbd2e3bc0d 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -306,7 +306,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given - // pair of array indices are unequal, so that when `places_conflict` returns true, we + // pair of array indices are not equal, so that when `places_conflict` returns true, we // will be assured that two places being compared definitely denotes the same sets of // locations. let definitely_conflicting_borrows = other_borrows_of_local.filter(|&i| { diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml new file mode 100644 index 00000000000..5f5510a5796 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml @@ -0,0 +1,64 @@ +name: Abi-cafe + +on: + - push + +jobs: + abi_cafe: + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.os }}-${{ matrix.env.TARGET_TRIPLE }} + cancel-in-progress: true + + defaults: + run: + shell: bash + + strategy: + fail-fast: true + matrix: + include: + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: macos-latest + env: + TARGET_TRIPLE: x86_64-apple-darwin + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-msvc + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu + + steps: + - uses: actions/checkout@v3 + + - name: Cache cargo target dir + uses: actions/cache@v3 + with: + path: build/cg_clif + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Set MinGW as the default toolchain + if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: rustup set default-host x86_64-pc-windows-gnu + + - name: Use sparse cargo registry + run: | + cat >> ~/.cargo/config.toml <<EOF + [unstable] + sparse-registry = true + EOF + + - name: Prepare dependencies + run: ./y.rs prepare + + - name: Build + run: ./y.rs build --sysroot none + + - name: Test abi-cafe + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} + run: ./y.rs abi-cafe diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 9d3ed3ac5d0..98b34c65dea 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: rustfmt --check build_system/mod.rs - build: + test: runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -114,63 +114,6 @@ jobs: run: ./y.rs test - abi_cafe: - runs-on: ${{ matrix.os }} - timeout-minutes: 60 - - defaults: - run: - shell: bash - - strategy: - fail-fast: true - matrix: - include: - - os: ubuntu-latest - env: - TARGET_TRIPLE: x86_64-unknown-linux-gnu - - os: macos-latest - env: - TARGET_TRIPLE: x86_64-apple-darwin - - os: windows-latest - env: - TARGET_TRIPLE: x86_64-pc-windows-msvc - - os: windows-latest - env: - TARGET_TRIPLE: x86_64-pc-windows-gnu - - steps: - - uses: actions/checkout@v3 - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: build/cg_clif - key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} - - - name: Set MinGW as the default toolchain - if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' - run: rustup set default-host x86_64-pc-windows-gnu - - - name: Use sparse cargo registry - run: | - cat >> ~/.cargo/config.toml <<EOF - [unstable] - sparse-registry = true - EOF - - - name: Prepare dependencies - run: ./y.rs prepare - - - name: Build - run: ./y.rs build --sysroot none - - - name: Test abi-cafe - env: - TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} - run: ./y.rs abi-cafe - - bench: runs-on: ubuntu-latest timeout-minutes: 60 diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore index 8012e93f6a9..e5d10a937ae 100644 --- a/compiler/rustc_codegen_cranelift/.gitignore +++ b/compiler/rustc_codegen_cranelift/.gitignore @@ -14,3 +14,4 @@ perf.data.old /dist /rust /download +/git-fixed-subtree.sh diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 50249ea1bdb..157ef4bf389 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -57,18 +57,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3d54eab028f5805ae3b26fd60eca3f3a9cfb76b989d9bab173be3f61356cc3" +checksum = "a7379abaacee0f14abf3204a7606118f0465785252169d186337bcb75030815a" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be1d5f2c3cca1efb691844bc1988b89c77291f13f778499a3f3c0cf49c0ed61" +checksum = "9489fa336927df749631f1008007ced2871068544f40a202ce6d93fbf2366a7b" dependencies = [ "arrayvec", "bumpalo", @@ -87,30 +87,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9b1b1089750ce4005893af7ee00bb08a2cf1c9779999c0f7164cbc8ad2e0d2" +checksum = "05bbb67da91ec721ed57cef2f7c5ef7728e1cd9bde9ffd3ef8601022e73e3239" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5fbaec51de47297fd7304986fd53c8c0030abbe69728a60d72e1c63559318d" +checksum = "418ecb2f36032f6665dc1a5e2060a143dbab41d83b784882e97710e890a7a16d" [[package]] name = "cranelift-entity" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab984c94593f876090fae92e984bdcc74d9b1acf740ab5f79036001c65cba13" +checksum = "7cf583f7b093f291005f9fb1323e2c37f6ee4c7909e39ce016b2e8360d461705" [[package]] name = "cranelift-frontend" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0cb3102d21a2fe5f3210af608748ddd0cd09825ac12d42dc56ed5ed8725fe0" +checksum = "7d361ed0373cf5f086b49c499aa72227b646a64f899f32e34312f97c0fadff75" dependencies = [ "cranelift-codegen", "log", @@ -120,15 +120,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.92.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72101dd1f441d629735143c41e00b3428f9267738176983ef588ff43382af0a0" +checksum = "649782a39ce99798dd6b4029e2bb318a2fbeaade1b4fa25330763c10c65bc358" [[package]] name = "cranelift-jit" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6557f8ce44d498777f2495aa58d9692a4a37d6f84aa445750d666cef770b6a5c" +checksum = "9c9909222db472fcc98d9e4e7192fa9d064dac63a3fa657df8c6daae86fb2604" dependencies = [ "anyhow", "cranelift-codegen", @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88807e1c0c47ec02fe433333ccbe56b480425418b1470e333205e11650697d72" +checksum = "68689b83e52e605ba48652882d3fccc2e2e136abf139eb64ae667888ba0d52f8" dependencies = [ "anyhow", "cranelift-codegen", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22b0d9fcbe3fc5a1af9e7021b44ce42b930bcefac446ce22e02e8f9a0d67120" +checksum = "f98e4e99a353703475d5acb402b9c13482d41d8a4008b352559bd560afb90363" dependencies = [ "cranelift-codegen", "libc", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341375758d7c3fedc0b5315f552e6f0feac46baf87c450a15e9455ef47c2b261" +checksum = "b7a006ce1d8dd11df67567d8673e5920f3a56441812aed52a007ffce8f1b20e9" dependencies = [ "anyhow", "cranelift-codegen", @@ -333,6 +333,7 @@ dependencies = [ "cranelift-frontend", "cranelift-jit", "cranelift-module", + "cranelift-native", "cranelift-object", "gimli", "indexmap", @@ -381,9 +382,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasmtime-jit-icache-coherence" -version = "5.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08fcba5ebd96da2a9f0747ab6337fe9788adfb3f63fa2c180520d665562d257e" +checksum = "ec1fd0f0dd79e7cc0f55b102e320d7c77ab76cd272008a8fd98e25b5777e2636" dependencies = [ "cfg-if", "libc", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 34117c2886f..0e64fba6bec 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -15,14 +15,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.92", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.92" } -cranelift-module = { version = "0.92" } -# NOTE vendored as src/cranelift_native.rs -# FIXME revert back to the external crate with Cranelift 0.93 -#cranelift-native = { version = "0.92" } -cranelift-jit = { version = "0.92", optional = true } -cranelift-object = { version = "0.92" } +cranelift-codegen = { version = "0.93", features = ["unwind", "all-arch"] } +cranelift-frontend = { version = "0.93" } +cranelift-module = { version = "0.93" } +cranelift-native = { version = "0.93" } +cranelift-jit = { version = "0.93", optional = true } +cranelift-object = { version = "0.93" } target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index b7e0b68a2a2..f2150762991 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -50,9 +50,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.86" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dae98c88e576098d7ab13ebcb40cc43e5114b2beafe61a87cda9200649ff205" +checksum = "9fc9c2080d347a2c316518840ac9194644a9993dfa1e9778ef38979a339f5d8b" dependencies = [ "rustc-std-workspace-core", ] @@ -117,21 +117,20 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" dependencies = [ "compiler_builtins", - "libc", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] [[package]] name = "libc" -version = "0.2.139" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" dependencies = [ "rustc-std-workspace-core", ] @@ -282,10 +281,8 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ - "cfg-if", "core", "getopts", - "libc", "panic_abort", "panic_unwind", "proc_macro", diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml index d0e5fc4a3b9..8219e6b6ccf 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml @@ -8,7 +8,7 @@ alloc = { path = "./sysroot_src/library/alloc" } std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } test = { path = "./sysroot_src/library/test" } -compiler_builtins = { version = "0.1.39", default-features = false, features = ["no-asm"] } +compiler_builtins = { version = "0.1.87", default-features = false, features = ["no-asm"] } [patch.crates-io] rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 2e04f2c6811..76b602fe719 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -46,13 +46,15 @@ pub(crate) fn build_sysroot( let wrapper_name = wrapper_base_name.replace("____", wrapper); let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc); + let wrapper_path = DIST_DIR.to_path(dirs).join(&wrapper_name); build_cargo_wrapper_cmd .env("TOOLCHAIN_NAME", toolchain_name.clone()) .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs"))) .arg("-o") - .arg(DIST_DIR.to_path(dirs).join(wrapper_name)) + .arg(&wrapper_path) .arg("-Cstrip=debuginfo"); spawn_and_wait(build_cargo_wrapper_cmd); + try_hard_link(wrapper_path, BIN_DIR.to_path(dirs).join(wrapper_name)); } let host = build_sysroot_for_triple( @@ -247,6 +249,7 @@ fn build_clif_sysroot_for_triple( if channel == "release" { build_cmd.arg("--release"); } + build_cmd.arg("--locked"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); if compiler.triple.contains("apple") { build_cmd.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed"); diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index 50b1b7836de..6769e42d44b 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -6,6 +6,7 @@ use std::process::Command; use super::build_sysroot::{BUILD_SYSROOT, ORIG_BUILD_SYSROOT, SYSROOT_RUSTC_VERSION, SYSROOT_SRC}; use super::path::{Dirs, RelPath}; use super::rustc_info::{get_default_sysroot, get_rustc_version}; +use super::tests::LIBCORE_TESTS_SRC; use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spawn_and_wait}; pub(crate) fn prepare(dirs: &Dirs) { @@ -13,8 +14,10 @@ pub(crate) fn prepare(dirs: &Dirs) { spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", "rustc", dirs)); - prepare_sysroot(dirs); + prepare_stdlib(dirs); spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", "rustc", dirs)); + + prepare_coretests(dirs); spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", "rustc", dirs)); super::tests::RAND_REPO.fetch(dirs); @@ -25,11 +28,11 @@ pub(crate) fn prepare(dirs: &Dirs) { spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", "rustc", dirs)); } -fn prepare_sysroot(dirs: &Dirs) { +fn prepare_stdlib(dirs: &Dirs) { let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust"); assert!(sysroot_src_orig.exists()); - eprintln!("[COPY] sysroot src"); + eprintln!("[COPY] stdlib src"); // FIXME ensure builds error out or update the copy if any of the files copied here change BUILD_SYSROOT.ensure_fresh(dirs); @@ -47,7 +50,25 @@ fn prepare_sysroot(dirs: &Dirs) { eprintln!("[GIT] init"); init_git_repo(&SYSROOT_SRC.to_path(dirs)); - apply_patches(dirs, "sysroot", &SYSROOT_SRC.to_path(dirs)); + apply_patches(dirs, "stdlib", &SYSROOT_SRC.to_path(dirs)); +} + +fn prepare_coretests(dirs: &Dirs) { + let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust"); + assert!(sysroot_src_orig.exists()); + + eprintln!("[COPY] coretests src"); + + fs::create_dir_all(LIBCORE_TESTS_SRC.to_path(dirs)).unwrap(); + copy_dir_recursively( + &sysroot_src_orig.join("library/core/tests"), + &LIBCORE_TESTS_SRC.to_path(dirs), + ); + + eprintln!("[GIT] init"); + init_git_repo(&LIBCORE_TESTS_SRC.to_path(dirs)); + + apply_patches(dirs, "coretests", &LIBCORE_TESTS_SRC.to_path(dirs)); } pub(crate) struct GitRepo { diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index e9486888f86..261948a6971 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -1,4 +1,4 @@ -use super::build_sysroot::{self, SYSROOT_SRC}; +use super::build_sysroot; use super::config; use super::path::{Dirs, RelPath}; use super::prepare::GitRepo; @@ -94,40 +94,42 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), ]; +// FIXME(rust-random/rand#1293): Newer rand versions fail to test on Windows. Update once this is +// fixed. pub(crate) static RAND_REPO: GitRepo = - GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand"); + GitRepo::github("rust-random", "rand", "50b9a447410860af8d6db9a208c3576886955874", "rand"); pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand"); pub(crate) static REGEX_REPO: GitRepo = - GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex"); + GitRepo::github("rust-lang", "regex", "a9b2e02352db92ce1f6e5b7ecd41b8bbffbe161a", "regex"); pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex"); pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "582239ac3b32007613df04d7ffa78dc30f4c5645", + "9bd30e77b3a3c699af102ebb3df0f6110f8aa02e", "portable-simd", ); pub(crate) static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd"); -pub(crate) static LIBCORE_TESTS: CargoProject = - CargoProject::new(&SYSROOT_SRC.join("library/core/tests"), "core_tests"); +pub(crate) static LIBCORE_TESTS_SRC: RelPath = RelPath::DOWNLOAD.join("coretests_src"); + +pub(crate) static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "core_tests"); const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.rust-random/rand", &|runner| { RAND.clean(&runner.dirs); if runner.is_native { - eprintln!("[TEST] rust-random/rand"); let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs); - test_cmd.arg("--workspace"); + test_cmd.arg("--workspace").arg("--").arg("-q"); spawn_and_wait(test_cmd); } else { - eprintln!("[AOT] rust-random/rand"); + eprintln!("Cross-Compiling: Not running tests"); let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs); build_cmd.arg("--workspace").arg("--tests"); spawn_and_wait(build_cmd); @@ -137,7 +139,9 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ LIBCORE_TESTS.clean(&runner.dirs); if runner.is_native { - spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs)); + let mut test_cmd = LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs); + test_cmd.arg("--").arg("-q"); + spawn_and_wait(test_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs); @@ -148,18 +152,13 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.regex-shootout-regex-dna", &|runner| { REGEX.clean(&runner.dirs); - // newer aho_corasick versions throw a deprecation warning - let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags); - let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs); build_cmd.arg("--example").arg("shootout-regex-dna"); - build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.is_native { let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs); run_cmd.arg("--example").arg("shootout-regex-dna"); - run_cmd.env("RUSTFLAGS", lint_rust_flags); let input = fs::read_to_string( REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"), @@ -171,13 +170,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ .unwrap(); let output = spawn_and_wait_with_input(run_cmd, input); - // Make sure `[codegen mono items] start` doesn't poison the diff - let output = output - .lines() - .filter(|line| !line.contains("codegen mono items")) - .chain(Some("")) // This just adds the trailing newline - .collect::<Vec<&str>>() - .join("\r\n"); let output_matches = expected.lines().eq(output.lines()); if !output_matches { @@ -192,27 +184,14 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.regex", &|runner| { REGEX.clean(&runner.dirs); - // newer aho_corasick versions throw a deprecation warning - let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags); - if runner.is_native { let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs); - run_cmd.args([ - "--tests", - "--", - "--exclude-should-panic", - "--test-threads", - "1", - "-Zunstable-options", - "-q", - ]); - run_cmd.env("RUSTFLAGS", lint_rust_flags); + run_cmd.args(["--workspace", "--", "-q"]); spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs); build_cmd.arg("--tests"); - build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); } }), diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 1f9db1eb2a9..73b83b89f6d 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -518,6 +518,17 @@ pub struct Box<T: ?Sized>(Unique<T>, ()); impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {} +impl<T> Box<T> { + pub fn new(val: T) -> Box<T> { + unsafe { + let size = intrinsics::size_of::<T>(); + let ptr = libc::malloc(size); + intrinsics::copy(&val as *const T as *const u8, ptr, size); + Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, ()) + } + } +} + impl<T: ?Sized> Drop for Box<T> { fn drop(&mut self) { // drop is currently performed by compiler. diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 04e7795bbfa..6ad3268e70d 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -1,16 +1,16 @@ -#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local)] +#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, repr_simd)] #![no_core] #![allow(dead_code, non_camel_case_types)] extern crate mini_core; -use mini_core::*; use mini_core::libc::*; +use mini_core::*; macro_rules! assert { ($e:expr) => { if !$e { - panic(stringify!(! $e)); + panic(stringify!(!$e)); } }; } @@ -20,7 +20,7 @@ macro_rules! assert_eq { if $l != $r { panic(stringify!($l != $r)); } - } + }; } #[lang = "termination"] @@ -96,9 +96,15 @@ fn start<T: Termination + 'static>( _sigpipe: u8, ) -> isize { if argc == 3 { - unsafe { puts(*argv as *const i8); } - unsafe { puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const i8)); } - unsafe { puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const i8)); } + unsafe { + puts(*argv as *const i8); + } + unsafe { + puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const i8)); + } + unsafe { + puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const i8)); + } } main().report() as isize @@ -107,7 +113,6 @@ fn start<T: Termination + 'static>( static mut NUM: u8 = 6 * 7; static NUM_REF: &'static u8 = unsafe { &NUM }; - unsafe fn zeroed<T>() -> T { let mut uninit = MaybeUninit { uninit: () }; intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1); @@ -144,10 +149,7 @@ extern "C" fn bool_struct_in_11(_arg0: bool_11) {} #[allow(unreachable_code)] // FIXME false positive fn main() { - take_unique(Unique { - pointer: unsafe { NonNull(1 as *mut ()) }, - _marker: PhantomData, - }); + take_unique(Unique { pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData }); take_f32(0.1); call_return_u128_pair(); @@ -202,17 +204,17 @@ fn main() { assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4); assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2); - assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8); + assert_eq!( + intrinsics::min_align_of_val(&a) as u8, + intrinsics::min_align_of::<&str>() as u8 + ); assert!(!intrinsics::needs_drop::<u8>()); assert!(!intrinsics::needs_drop::<[u8]>()); assert!(intrinsics::needs_drop::<NoisyDrop>()); assert!(intrinsics::needs_drop::<NoisyDropUnsized>()); - Unique { - pointer: NonNull(1 as *mut &str), - _marker: PhantomData, - } as Unique<dyn SomeTrait>; + Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique<dyn SomeTrait>; struct MyDst<T: ?Sized>(T); @@ -238,19 +240,17 @@ fn main() { } } - let _ = Box::new(NoisyDrop { - text: "Boxed outer got dropped!\0", - inner: NoisyDropInner, - }) as Box<dyn SomeTrait>; + let _ = Box::new(NoisyDrop { text: "Boxed outer got dropped!\0", inner: NoisyDropInner }) + as Box<dyn SomeTrait>; const FUNC_REF: Option<fn()> = Some(main); match FUNC_REF { - Some(_) => {}, + Some(_) => {} None => assert!(false), } match Ordering::Less { - Ordering::Less => {}, + Ordering::Less => {} _ => assert!(false), } @@ -266,19 +266,21 @@ fn main() { #[cfg(not(any(jit, windows)))] { - extern { + extern "C" { #[linkage = "extern_weak"] static ABC: *const u8; } { - extern { + extern "C" { #[linkage = "extern_weak"] static ABC: *const u8; } } - unsafe { assert_eq!(ABC as usize, 0); } + unsafe { + assert_eq!(ABC as usize, 0); + } } &mut (|| Some(0 as *const ())) as &mut dyn FnMut() -> Option<*const ()>; @@ -339,7 +341,13 @@ fn main() { assert_eq!(unsafe { intrinsics::size_of_val(x) }, 0); assert_eq!(unsafe { intrinsics::min_align_of_val(x) }, 1); -} + } + + #[repr(simd)] + struct V([f64; 2]); + + let f = V([0.0, 1.0]); + let _a = f.0[0]; } #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] @@ -392,13 +400,10 @@ extern "C" { native: *mut pthread_t, attr: *const pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, - value: *mut c_void + value: *mut c_void, ) -> c_int; - fn pthread_join( - native: pthread_t, - value: *mut *mut c_void - ) -> c_int; + fn pthread_join(native: pthread_t, value: *mut *mut c_void) -> c_int; } type DWORD = u32; @@ -410,10 +415,7 @@ type HANDLE = *mut c_void; #[link(name = "msvcrt")] #[cfg(windows)] extern "C" { - fn WaitForSingleObject( - hHandle: LPVOID, - dwMilliseconds: DWORD - ) -> DWORD; + fn WaitForSingleObject(hHandle: LPVOID, dwMilliseconds: DWORD) -> DWORD; fn CreateThread( lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway @@ -421,7 +423,7 @@ extern "C" { lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, lpParameter: LPVOID, dwCreationFlags: DWORD, - lpThreadId: LPDWORD + lpThreadId: LPDWORD, ) -> HANDLE; } @@ -447,9 +449,7 @@ impl Thread { assert!(false); } - Thread { - handle: thread, - } + Thread { handle: thread } } #[cfg(windows)] @@ -460,13 +460,10 @@ impl Thread { assert!(false); } - Thread { - handle, - } + Thread { handle } } } - unsafe fn join(self) { #[cfg(unix)] { @@ -483,16 +480,15 @@ impl Thread { } } - - - #[thread_local] #[cfg(not(jit))] static mut TLS: u8 = 42; #[cfg(not(jit))] extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void { - unsafe { TLS = 0; } + unsafe { + TLS = 0; + } 0 as *mut c_void } @@ -531,44 +527,267 @@ pub enum E1 { pub enum E2<X> { V1 { f: bool }, - /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), - _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), - _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), - _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), - _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), - _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), - _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), - _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), - _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), - _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), - _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), - _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), - _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), - _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), - _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), - _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), - _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), - _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), - _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), - _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), - _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), - _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), - _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), - _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), - _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), - _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), - _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), - _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), - _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), - _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), - _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), - _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + /*_00*/ _01(X), + _02(X), + _03(X), + _04(X), + _05(X), + _06(X), + _07(X), + _08(X), + _09(X), + _0A(X), + _0B(X), + _0C(X), + _0D(X), + _0E(X), + _0F(X), + _10(X), + _11(X), + _12(X), + _13(X), + _14(X), + _15(X), + _16(X), + _17(X), + _18(X), + _19(X), + _1A(X), + _1B(X), + _1C(X), + _1D(X), + _1E(X), + _1F(X), + _20(X), + _21(X), + _22(X), + _23(X), + _24(X), + _25(X), + _26(X), + _27(X), + _28(X), + _29(X), + _2A(X), + _2B(X), + _2C(X), + _2D(X), + _2E(X), + _2F(X), + _30(X), + _31(X), + _32(X), + _33(X), + _34(X), + _35(X), + _36(X), + _37(X), + _38(X), + _39(X), + _3A(X), + _3B(X), + _3C(X), + _3D(X), + _3E(X), + _3F(X), + _40(X), + _41(X), + _42(X), + _43(X), + _44(X), + _45(X), + _46(X), + _47(X), + _48(X), + _49(X), + _4A(X), + _4B(X), + _4C(X), + _4D(X), + _4E(X), + _4F(X), + _50(X), + _51(X), + _52(X), + _53(X), + _54(X), + _55(X), + _56(X), + _57(X), + _58(X), + _59(X), + _5A(X), + _5B(X), + _5C(X), + _5D(X), + _5E(X), + _5F(X), + _60(X), + _61(X), + _62(X), + _63(X), + _64(X), + _65(X), + _66(X), + _67(X), + _68(X), + _69(X), + _6A(X), + _6B(X), + _6C(X), + _6D(X), + _6E(X), + _6F(X), + _70(X), + _71(X), + _72(X), + _73(X), + _74(X), + _75(X), + _76(X), + _77(X), + _78(X), + _79(X), + _7A(X), + _7B(X), + _7C(X), + _7D(X), + _7E(X), + _7F(X), + _80(X), + _81(X), + _82(X), + _83(X), + _84(X), + _85(X), + _86(X), + _87(X), + _88(X), + _89(X), + _8A(X), + _8B(X), + _8C(X), + _8D(X), + _8E(X), + _8F(X), + _90(X), + _91(X), + _92(X), + _93(X), + _94(X), + _95(X), + _96(X), + _97(X), + _98(X), + _99(X), + _9A(X), + _9B(X), + _9C(X), + _9D(X), + _9E(X), + _9F(X), + _A0(X), + _A1(X), + _A2(X), + _A3(X), + _A4(X), + _A5(X), + _A6(X), + _A7(X), + _A8(X), + _A9(X), + _AA(X), + _AB(X), + _AC(X), + _AD(X), + _AE(X), + _AF(X), + _B0(X), + _B1(X), + _B2(X), + _B3(X), + _B4(X), + _B5(X), + _B6(X), + _B7(X), + _B8(X), + _B9(X), + _BA(X), + _BB(X), + _BC(X), + _BD(X), + _BE(X), + _BF(X), + _C0(X), + _C1(X), + _C2(X), + _C3(X), + _C4(X), + _C5(X), + _C6(X), + _C7(X), + _C8(X), + _C9(X), + _CA(X), + _CB(X), + _CC(X), + _CD(X), + _CE(X), + _CF(X), + _D0(X), + _D1(X), + _D2(X), + _D3(X), + _D4(X), + _D5(X), + _D6(X), + _D7(X), + _D8(X), + _D9(X), + _DA(X), + _DB(X), + _DC(X), + _DD(X), + _DE(X), + _DF(X), + _E0(X), + _E1(X), + _E2(X), + _E3(X), + _E4(X), + _E5(X), + _E6(X), + _E7(X), + _E8(X), + _E9(X), + _EA(X), + _EB(X), + _EC(X), + _ED(X), + _EE(X), + _EF(X), + _F0(X), + _F1(X), + _F2(X), + _F3(X), + _F4(X), + _F5(X), + _F6(X), + _F7(X), + _F8(X), + _F9(X), + _FA(X), + _FB(X), + _FC(X), + _FD(X), + _FE(X), + _FF(X), V3, V4, } -fn check_niche_behavior () { +fn check_niche_behavior() { if let E1::V2 { .. } = (E1::V1 { f: true }) { intrinsics::abort(); } diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 8481d9c39a3..e34b35d5c4a 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -58,8 +58,9 @@ fn main() { assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128); - let _d = 0i128.checked_div(2i128); - let _d = 0u128.checked_div(2u128); + std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10); + assert!(0i128.checked_div(2i128).is_some()); + assert!(0u128.checked_div(2u128).is_some()); assert_eq!(1u128 + 2, 3); assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128); diff --git a/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch index d8775e2d022..eb452c5cd37 100644 --- a/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch +++ b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch @@ -19,8 +19,8 @@ index 217899e..9cedeb7 100644 + // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation + #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] fn value_stability() { - fn test_samples<F: Float + core::fmt::Debug, D: Distribution<F>>( - distr: D, zero: F, expected: &[F], + fn test_samples<F: Float + Debug + Display + LowerExp, D: Distribution<F>>( + distr: D, thresh: F, expected: &[F], diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs index 192ba74..0101ace 100644 --- a/rand_distr/tests/value_stability.rs diff --git a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch index 865aa833a5e..6afa5c71fe5 100644 --- a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -13,14 +13,14 @@ Subject: [PATCH] [core] Disable not compiling tests 6 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 library/core/tests/Cargo.toml -diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml +diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..46fd999 --- /dev/null -+++ b/library/core/tests/Cargo.toml ++++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] -+name = "core" ++name = "coretests" +version = "0.0.0" +edition = "2021" + @@ -31,5 +31,14 @@ index 0000000..46fd999 +[dependencies] +rand = { version = "0.8.5", default-features = false } +rand_xorshift = { version = "0.3.0", default-features = false } +diff --git a/lib.rs b/lib.rs +index 42a26ae..5ac1042 100644 +--- a/lib.rs ++++ b/lib.rs +@@ -1,3 +1,4 @@ ++#![cfg(test)] + #![feature(alloc_layout_extra)] + #![feature(array_chunks)] + #![feature(array_methods)] -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch index f3cd7ee77e2..f2cb82751f0 100644 --- a/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch @@ -10,10 +10,10 @@ Subject: [PATCH] [core] Ignore failing tests library/core/tests/time.rs | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) -diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs +diff --git a/array.rs b/array.rs index 4bc44e9..8e3c7a4 100644 ---- a/library/core/tests/array.rs -+++ b/library/core/tests/array.rs +--- a/array.rs ++++ b/array.rs @@ -242,6 +242,7 @@ fn iterator_drops() { assert_eq!(i.get(), 5); } @@ -46,10 +46,10 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { -diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs +diff --git a/atomic.rs b/atomic.rs index 13b12db..96fe4b9 100644 ---- a/library/core/tests/atomic.rs -+++ b/library/core/tests/atomic.rs +--- a/atomic.rs ++++ b/atomic.rs @@ -185,6 +185,7 @@ fn ptr_bitops() { } diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch new file mode 100644 index 00000000000..1d5479bedde --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -0,0 +1,30 @@ +From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 +From: bjorn3 <bjorn3@users.noreply.github.com> +Date: Thu, 18 Feb 2021 18:45:28 +0100 +Subject: [PATCH] Disable 128bit atomic operations + +Cranelift doesn't support them yet +--- + library/core/src/panic/unwind_safe.rs | 6 ----- + library/core/src/sync/atomic.rs | 38 --------------------------- + library/core/tests/atomic.rs | 4 --- + 4 files changed, 4 insertions(+), 50 deletions(-) + +diff --git a/atomic.rs b/atomic.rs +index b735957..ea728b6 100644 +--- a/atomic.rs ++++ b/atomic.rs +@@ -185,10 +185,6 @@ fn atomic_alignment() { + assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>()); + #[cfg(target_has_atomic = "64")] + assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>()); +- #[cfg(target_has_atomic = "128")] +- assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>()); +- #[cfg(target_has_atomic = "128")] +- assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>()); + #[cfg(target_has_atomic = "ptr")] + assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>()); + #[cfg(target_has_atomic = "ptr")] +-- +2.26.2.7.g19db9cfb68 + diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch index 77f437974c2..45f73f36b93 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch @@ -85,21 +85,6 @@ index d9de37e..8293fce 100644 macro_rules! atomic_int_ptr_sized { ( $($target_pointer_width:literal $align:literal)* ) => { $( -diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs -index b735957..ea728b6 100644 ---- a/library/core/tests/atomic.rs -+++ b/library/core/tests/atomic.rs -@@ -185,10 +185,6 @@ fn atomic_alignment() { - assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>()); - #[cfg(target_has_atomic = "64")] - assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>()); -- #[cfg(target_has_atomic = "128")] -- assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>()); -- #[cfg(target_has_atomic = "128")] -- assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>()); - #[cfg(target_has_atomic = "ptr")] - assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>()); - #[cfg(target_has_atomic = "ptr")] -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch index d804a78cc10..440177018f4 100644 --- a/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Disable long running tests library/core/tests/slice.rs | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +diff --git a/slice.rs b/slice.rs index 8402833..84592e0 100644 ---- a/library/core/tests/slice.rs -+++ b/library/core/tests/slice.rs +--- a/slice.rs ++++ b/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { assert!(v == [0xDEADBEEF]); } diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 40fb54b9159..2236a6ca155 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-02-06" +channel = "nightly-2023-03-15" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs index c993430b830..939a1f1ca59 100644 --- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs @@ -1,11 +1,14 @@ use std::env; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let mut rustflags = String::new(); rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs index c187f54a60e..b9bba7f2e08 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs @@ -2,11 +2,14 @@ use std::env; use std::ffi::OsString; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs index a6528ac41ae..167631eaf7e 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs @@ -2,11 +2,14 @@ use std::env; use std::ffi::OsString; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index 34e3981b538..3cbeb6375de 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -2,10 +2,24 @@ set -e +TOOLCHAIN=${TOOLCHAIN:-$(date +%Y-%m-%d)} + +function check_git_fixed_subtree() { + if [[ ! -e ./git-fixed-subtree.sh ]]; then + echo "Missing git-fixed-subtree.sh. Please run the following commands to download it:" + echo "curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/bjorn3/git/tqc-subtree-portable/contrib/subtree/git-subtree.sh -o git-fixed-subtree.sh" + echo "chmod u+x git-fixed-subtree.sh" + exit 1 + fi + if [[ ! -x ./git-fixed-subtree.sh ]]; then + echo "git-fixed-subtree.sh is not executable. Please run the following command to make it executable:" + echo "chmod u+x git-fixed-subtree.sh" + exit 1 + fi +} + case $1 in "prepare") - TOOLCHAIN=$(date +%Y-%m-%d) - echo "=> Installing new nightly" rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain @@ -27,28 +41,35 @@ case $1 in git commit -m "Rustup to $(rustc -V)" ;; "push") + check_git_fixed_subtree + cg_clif=$(pwd) pushd ../rust git pull origin master branch=sync_cg_clif-$(date +%Y-%m-%d) git checkout -b "$branch" - git subtree pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master + "$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master git push -u my "$branch" # immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing # from rust-lang/rust later - git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust + "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd git merge sync_from_rust ;; "pull") + check_git_fixed_subtree + + RUST_VERS=$(curl "https://static.rust-lang.org/dist/$TOOLCHAIN/channel-rust-nightly-git-commit-hash.txt") + echo "Pulling $RUST_VERS ($TOOLCHAIN)" + cg_clif=$(pwd) pushd ../rust - git pull origin master - rust_vers="$(git rev-parse HEAD)" - git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust + git fetch origin master + git checkout "$RUST_VERS" + "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd - git merge sync_from_rust -m "Sync from rust $rust_vers" + git merge sync_from_rust -m "Sync from rust $RUST_VERS" git branch -d sync_from_rust ;; *) diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index a08e80dd19a..abb09775d21 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -10,7 +10,7 @@ git fetch git checkout -- . git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" -git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-sysroot-*.patch +git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-stdlib-*.patch git apply - <<EOF diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml @@ -36,7 +36,7 @@ changelog-seen = 2 ninja = false [build] -rustc = "$(pwd)/../dist/rustc-clif" +rustc = "$(pwd)/../dist/bin/rustc-clif" cargo = "$(rustup which cargo)" full-bootstrap = true local-rebuild = true diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index e14a129dbc2..20dcb4cf34d 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -21,6 +21,7 @@ done git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed git checkout -- tests/ui/proc-macro/pretty-print-hack/ +rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # missing features # ================ @@ -80,6 +81,7 @@ rm tests/ui/layout/valid_range_oob.rs # different ICE message rm tests/ui/consts/issue-miri-1910.rs # different error message rm tests/ui/consts/offset_ub.rs # same +rm tests/ui/consts/const-eval/ub-slice-get-unchecked.rs # same rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/lint/lint-const-item-mutation.rs # same rm tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs # same @@ -110,12 +112,9 @@ rm tests/incremental/spike-neg2.rs # same rm tests/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors -rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type filed (#1318) +rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type field (#1318) rm tests/ui/simd/simd-bitmask.rs # crash -rm tests/ui/dyn-star/dyn-star-to-dyn.rs -rm tests/ui/dyn-star/dispatch-on-pin-mut.rs - # bugs in the test suite # ====================== rm tests/ui/backtrace.rs # TODO warning diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 74396a66f54..3bc64c44524 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -4,6 +4,8 @@ mod comments; mod pass_mode; mod returning; +use std::borrow::Cow; + use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; @@ -25,7 +27,7 @@ fn clif_sig_from_fn_abi<'tcx>( ) -> Signature { let call_conv = conv_to_call_conv(tcx.sess, fn_abi.conv, default_call_conv); - let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten(); + let inputs = fn_abi.args.iter().flat_map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()); let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx); // Sometimes the first param is an pointer to the place where the return value needs to be stored. @@ -116,7 +118,52 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { params: Vec<AbiParam>, returns: Vec<AbiParam>, args: &[Value], - ) -> &[Value] { + ) -> Cow<'_, [Value]> { + if self.tcx.sess.target.is_like_windows { + let (mut params, mut args): (Vec<_>, Vec<_>) = + params + .into_iter() + .zip(args) + .map(|(param, &arg)| { + if param.value_type == types::I128 { + let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot( + StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 }, + )); + arg_ptr.store(self, arg, MemFlags::trusted()); + (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) + } else { + (param, arg) + } + }) + .unzip(); + + let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128; + + if indirect_ret_val { + params.insert(0, AbiParam::new(self.pointer_type)); + let ret_ptr = + Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: 16, + })); + args.insert(0, ret_ptr.get_addr(self)); + self.lib_call_unadjusted(name, params, vec![], &args); + return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]); + } else { + return self.lib_call_unadjusted(name, params, returns, &args); + } + } + + self.lib_call_unadjusted(name, params, returns, args) + } + + pub(crate) fn lib_call_unadjusted( + &mut self, + name: &str, + params: Vec<AbiParam>, + returns: Vec<AbiParam>, + args: &[Value], + ) -> Cow<'_, [Value]> { let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); @@ -125,41 +172,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } let call_inst = self.bcx.ins().call(func_ref, args); if self.clif_comments.enabled() { - self.add_comment(call_inst, format!("easy_call {}", name)); + self.add_comment(call_inst, format!("lib_call {}", name)); } let results = self.bcx.inst_results(call_inst); assert!(results.len() <= 2, "{}", results.len()); - results - } - - pub(crate) fn easy_call( - &mut self, - name: &str, - args: &[CValue<'tcx>], - return_ty: Ty<'tcx>, - ) -> CValue<'tcx> { - let (input_tys, args): (Vec<_>, Vec<_>) = args - .iter() - .map(|arg| { - (AbiParam::new(self.clif_type(arg.layout().ty).unwrap()), arg.load_scalar(self)) - }) - .unzip(); - let return_layout = self.layout_of(return_ty); - let return_tys = if let ty::Tuple(tup) = return_ty.kind() { - tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() - } else { - vec![AbiParam::new(self.clif_type(return_ty).unwrap())] - }; - let ret_vals = self.lib_call(name, input_tys, return_tys, &args); - match *ret_vals { - [] => CValue::by_ref( - Pointer::const_addr(self, i64::from(self.pointer_type.bytes())), - return_layout, - ), - [val] => CValue::by_val(val, return_layout), - [val, extra] => CValue::by_val_pair(val, extra, return_layout), - _ => unreachable!(), - } + Cow::Borrowed(results) } } @@ -275,10 +292,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ self::comments::add_locals_header_comment(fx); for (local, arg_kind, ty) in func_params { - let layout = fx.layout_of(ty); - - let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa; - // While this is normally an optimization to prevent an unnecessary copy when an argument is // not mutated by the current function, this is necessary to support unsized arguments. if let ArgKind::Normal(Some(val)) = arg_kind { @@ -300,6 +313,8 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ } } + let layout = fx.layout_of(ty); + let is_ssa = ssa_analyzed[local].is_ssa(fx, ty); let place = make_local_place(fx, local, layout, is_ssa); assert_eq!(fx.local_map.push(place), local); @@ -323,7 +338,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ let ty = fx.monomorphize(fx.mir.local_decls[local].ty); let layout = fx.layout_of(ty); - let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa; + let is_ssa = ssa_analyzed[local].is_ssa(fx, ty); let place = make_local_place(fx, local, layout, is_ssa); assert_eq!(fx.local_map.push(place), local); @@ -515,10 +530,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.into_iter() .enumerate() .skip(if first_arg_override.is_some() { 1 } else { 0 }) - .map(|(i, arg)| { + .flat_map(|(i, arg)| { adjust_arg_for_abi(fx, arg.value, &fn_abi.args[i], arg.is_owned).into_iter() - }) - .flatten(), + }), ) .collect::<Vec<Value>>(); diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs index aaa1418767a..6d3e8eda276 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs @@ -14,7 +14,8 @@ pub(super) fn codegen_return_param<'tcx>( ) -> CPlace<'tcx> { let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode { PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => { - let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa; + let is_ssa = + ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty); ( super::make_local_place( fx, diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index 0cbb9f3ec2d..54d5c1c2ae9 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -4,34 +4,30 @@ use crate::prelude::*; use rustc_index::vec::IndexVec; use rustc_middle::mir::StatementKind::*; +use rustc_middle::ty::Ty; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) enum SsaKind { NotSsa, - Ssa, + MaybeSsa, +} + +impl SsaKind { + pub(crate) fn is_ssa<'tcx>(self, fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { + self == SsaKind::MaybeSsa && (fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some()) + } } pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec<Local, SsaKind> { - let mut flag_map = fx - .mir - .local_decls - .iter() - .map(|local_decl| { - let ty = fx.monomorphize(local_decl.ty); - if fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some() { - SsaKind::Ssa - } else { - SsaKind::NotSsa - } - }) - .collect::<IndexVec<Local, SsaKind>>(); + let mut flag_map = + fx.mir.local_decls.iter().map(|_| SsaKind::MaybeSsa).collect::<IndexVec<Local, SsaKind>>(); for bb in fx.mir.basic_blocks.iter() { for stmt in bb.statements.iter() { match &stmt.kind { Assign(place_and_rval) => match &place_and_rval.1 { Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - not_ssa(&mut flag_map, place.local) + flag_map[place.local] = SsaKind::NotSsa; } _ => {} }, @@ -42,7 +38,3 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec<Local, SsaKind> { flag_map } - -fn not_ssa(flag_map: &mut IndexVec<Local, SsaKind>, local: Local) { - flag_map[local] = SsaKind::NotSsa; -} diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 230256ba5aa..d0af3729b23 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -192,7 +192,7 @@ pub(crate) fn compile_fn( let pass_times = cranelift_codegen::timing::take_current(); // Replace newlines with | as measureme doesn't allow control characters like // newlines inside strings. - recorder.record_arg(format!("{}", pass_times).replace("\n", " | ")); + recorder.record_arg(format!("{}", pass_times).replace('\n', " | ")); recording_args = true; }, ) @@ -365,11 +365,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx.bcx.set_cold_block(failure); if *expected { - fx.bcx.ins().brz(cond, failure, &[]); + fx.bcx.ins().brif(cond, target, &[], failure, &[]); } else { - fx.bcx.ins().brnz(cond, failure, &[]); + fx.bcx.ins().brif(cond, failure, &[], target, &[]); }; - fx.bcx.ins().jump(target, &[]); fx.bcx.switch_to_block(failure); fx.bcx.ins().nop(); @@ -425,11 +424,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } } else { if test_zero { - fx.bcx.ins().brz(discr, then_block, &[]); - fx.bcx.ins().jump(else_block, &[]); + fx.bcx.ins().brif(discr, else_block, &[], then_block, &[]); } else { - fx.bcx.ins().brnz(discr, then_block, &[]); - fx.bcx.ins().jump(else_block, &[]); + fx.bcx.ins().brif(discr, then_block, &[], else_block, &[]); } } } else { @@ -750,8 +747,7 @@ fn codegen_stmt<'tcx>( fx.bcx.switch_to_block(loop_block); let done = fx.bcx.ins().icmp_imm(IntCC::Equal, index, times as i64); - fx.bcx.ins().brnz(done, done_block, &[]); - fx.bcx.ins().jump(loop_block2, &[]); + fx.bcx.ins().brif(done, done_block, &[], loop_block2, &[]); fx.bcx.switch_to_block(loop_block2); let to = lval.place_index(fx, index); @@ -997,7 +993,7 @@ fn codegen_panic_inner<'tcx>( let symbol_name = fx.tcx.symbol_name(instance).name; fx.lib_call( - &*symbol_name, + symbol_name, args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(), vec![], args, diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index 5091c5a9fed..032d1151041 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -64,17 +64,12 @@ pub(crate) fn clif_int_or_float_cast( }, ); - let from_rust_ty = if from_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - - let to_rust_ty = match to_ty { - types::F32 => fx.tcx.types.f32, - types::F64 => fx.tcx.types.f64, - _ => unreachable!(), - }; - - return fx - .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx); + return fx.lib_call( + &name, + vec![AbiParam::new(types::I128)], + vec![AbiParam::new(to_ty)], + &[from], + )[0]; } // int-like -> float @@ -101,16 +96,29 @@ pub(crate) fn clif_int_or_float_cast( }, ); - let from_rust_ty = match from_ty { - types::F32 => fx.tcx.types.f32, - types::F64 => fx.tcx.types.f64, - _ => unreachable!(), - }; - - let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - - fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx) + if fx.tcx.sess.target.is_like_windows { + let ret = fx.lib_call( + &name, + vec![AbiParam::new(from_ty)], + vec![AbiParam::new(types::I64X2)], + &[from], + )[0]; + // FIXME use bitcast instead of store to get from i64x2 to i128 + let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: 16, + }); + let ret_ptr = Pointer::stack_slot(stack_slot); + ret_ptr.store(fx, ret, MemFlags::trusted()); + ret_ptr.load(fx, types::I128, MemFlags::trusted()) + } else { + fx.lib_call( + &name, + vec![AbiParam::new(from_ty)], + vec![AbiParam::new(types::I128)], + &[from], + )[0] + } } else if to_ty == types::I8 || to_ty == types::I16 { // FIXME implement fcvt_to_*int_sat.i8/i16 let val = if to_signed { diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index 40bfe70771c..f674ce776a6 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -29,39 +29,24 @@ pub(crate) fn maybe_codegen<'tcx>( BinOp::Add | BinOp::Sub if !checked => None, BinOp::Mul if !checked || is_signed => { if !checked { - let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - if fx.tcx.sess.target.is_like_windows { - let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - let args = [ - ret_place.to_ptr().get_addr(fx), - lhs_ptr.get_addr(fx), - rhs_ptr.get_addr(fx), - ]; - fx.lib_call( - "__multi3", - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - ], - vec![], - &args, - ); - Some(ret_place.to_cvalue(fx)) - } else { - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) - } + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + "__multi3", + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val( + ret_val, + fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }), + )) } else { let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); let lhs = lhs.load_scalar(fx); let rhs = rhs.load_scalar(fx); let oflow_ptr = oflow.to_ptr().get_addr(fx); - let res = fx.lib_call( + let res = fx.lib_call_unadjusted( "__muloti4", vec![ AbiParam::new(types::I128), @@ -80,29 +65,12 @@ pub(crate) fn maybe_codegen<'tcx>( assert!(checked); let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); - let (param_types, args) = if fx.tcx.sess.target.is_like_windows { - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - ( - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - ], - [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], - ) - } else { - ( - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(types::I128), - AbiParam::new(types::I128), - ], - [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)], - ) - }; + let param_types = vec![ + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), + AbiParam::new(types::I128), + AbiParam::new(types::I128), + ]; + let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; let name = match (bin_op, is_signed) { (BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, true) => "__rust_i128_addo", @@ -125,14 +93,10 @@ pub(crate) fn maybe_codegen<'tcx>( _ => unreachable!(), }; if fx.tcx.sess.target.is_like_windows { - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; let ret = fx.lib_call( name, - vec![AbiParam::new(fx.pointer_type), AbiParam::new(fx.pointer_type)], + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], vec![AbiParam::new(types::I64X2)], &args, )[0]; @@ -141,7 +105,14 @@ pub(crate) fn maybe_codegen<'tcx>( ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); Some(ret_place.to_cvalue(fx)) } else { - Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + name, + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val(ret_val, lhs.layout())) } } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 722e2754e83..d39bf700035 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -75,7 +75,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ ty::Adt(adt_def, _) if adt_def.repr().simd() => { let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi { - Abi::Vector { element, count } => (element.clone(), *count), + Abi::Vector { element, count } => (*element, *count), _ => unreachable!(), }; diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs index 8a53baa763a..f3b963200a0 100644 --- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs +++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs @@ -39,6 +39,7 @@ builtin_functions! { // integers fn __multi3(a: i128, b: i128) -> i128; + fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128; fn __udivti3(n: u128, d: u128) -> u128; fn __divti3(n: i128, d: i128) -> i128; fn __umodti3(n: u128, d: u128) -> u128; diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index f855e20e0a1..203219a8a75 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -32,7 +32,7 @@ impl ConcurrencyLimiter { ConcurrencyLimiter { helper_thread: Some(helper_thread), state, - available_token_condvar: Arc::new(Condvar::new()), + available_token_condvar, finished: false, } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index efdf9f6d5bc..31278f810e9 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -290,7 +290,7 @@ fn data_id_for_static( }; let data_id = match module.declare_data( - &*symbol_name, + symbol_name, linkage, is_mutable, attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL), @@ -338,7 +338,7 @@ fn data_id_for_static( }; let data_id = match module.declare_data( - &*symbol_name, + symbol_name, linkage, is_mutable, attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL), diff --git a/compiler/rustc_codegen_cranelift/src/cranelift_native.rs b/compiler/rustc_codegen_cranelift/src/cranelift_native.rs deleted file mode 100644 index 6c4efca4424..00000000000 --- a/compiler/rustc_codegen_cranelift/src/cranelift_native.rs +++ /dev/null @@ -1,248 +0,0 @@ -// Vendored from https://github.com/bytecodealliance/wasmtime/blob/b58a197d33f044193c3d608010f5e6ec394ac07e/cranelift/native/src/lib.rs -// which is licensed as -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// unlike rustc_codegen_cranelift itself. Also applies a small change to remove #![cfg_attr] that -// rust's CI complains about and to fix formatting to match rustc. -// FIXME revert back to the external crate with Cranelift 0.93 -#![allow(warnings)] - -//! Performs autodetection of the host for the purposes of running -//! Cranelift to generate code to run on the same machine. - -#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)] -#![warn(unused_import_braces)] - -use cranelift_codegen::isa; -use target_lexicon::Triple; - -/// Return an `isa` builder configured for the current host -/// machine, or `Err(())` if the host machine is not supported -/// in the current configuration. -pub fn builder() -> Result<isa::Builder, &'static str> { - builder_with_options(true) -} - -/// Return an `isa` builder configured for the current host -/// machine, or `Err(())` if the host machine is not supported -/// in the current configuration. -/// -/// Selects the given backend variant specifically; this is -/// useful when more than oen backend exists for a given target -/// (e.g., on x86-64). -pub fn builder_with_options(infer_native_flags: bool) -> Result<isa::Builder, &'static str> { - let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err { - isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", - isa::LookupError::Unsupported => "unsupported architecture", - })?; - - #[cfg(target_arch = "x86_64")] - { - use cranelift_codegen::settings::Configurable; - - if !std::is_x86_feature_detected!("sse2") { - return Err("x86 support requires SSE2"); - } - - if !infer_native_flags { - return Ok(isa_builder); - } - - // These are temporarily enabled by default (see #3810 for - // more) so that a default-constructed `Flags` can work with - // default Wasmtime features. Otherwise, the user must - // explicitly use native flags or turn these on when on x86-64 - // platforms to avoid a configuration panic. In order for the - // "enable if detected" logic below to work, we must turn them - // *off* (differing from the default) and then re-enable below - // if present. - isa_builder.set("has_sse3", "false").unwrap(); - isa_builder.set("has_ssse3", "false").unwrap(); - isa_builder.set("has_sse41", "false").unwrap(); - isa_builder.set("has_sse42", "false").unwrap(); - - if std::is_x86_feature_detected!("sse3") { - isa_builder.enable("has_sse3").unwrap(); - } - if std::is_x86_feature_detected!("ssse3") { - isa_builder.enable("has_ssse3").unwrap(); - } - if std::is_x86_feature_detected!("sse4.1") { - isa_builder.enable("has_sse41").unwrap(); - } - if std::is_x86_feature_detected!("sse4.2") { - isa_builder.enable("has_sse42").unwrap(); - } - if std::is_x86_feature_detected!("popcnt") { - isa_builder.enable("has_popcnt").unwrap(); - } - if std::is_x86_feature_detected!("avx") { - isa_builder.enable("has_avx").unwrap(); - } - if std::is_x86_feature_detected!("avx2") { - isa_builder.enable("has_avx2").unwrap(); - } - if std::is_x86_feature_detected!("fma") { - isa_builder.enable("has_fma").unwrap(); - } - if std::is_x86_feature_detected!("bmi1") { - isa_builder.enable("has_bmi1").unwrap(); - } - if std::is_x86_feature_detected!("bmi2") { - isa_builder.enable("has_bmi2").unwrap(); - } - if std::is_x86_feature_detected!("avx512bitalg") { - isa_builder.enable("has_avx512bitalg").unwrap(); - } - if std::is_x86_feature_detected!("avx512dq") { - isa_builder.enable("has_avx512dq").unwrap(); - } - if std::is_x86_feature_detected!("avx512f") { - isa_builder.enable("has_avx512f").unwrap(); - } - if std::is_x86_feature_detected!("avx512vl") { - isa_builder.enable("has_avx512vl").unwrap(); - } - if std::is_x86_feature_detected!("avx512vbmi") { - isa_builder.enable("has_avx512vbmi").unwrap(); - } - if std::is_x86_feature_detected!("lzcnt") { - isa_builder.enable("has_lzcnt").unwrap(); - } - } - - #[cfg(target_arch = "aarch64")] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - if std::arch::is_aarch64_feature_detected!("lse") { - isa_builder.enable("has_lse").unwrap(); - } - - if std::arch::is_aarch64_feature_detected!("paca") { - isa_builder.enable("has_pauth").unwrap(); - } - - if cfg!(target_os = "macos") { - // Pointer authentication is always available on Apple Silicon. - isa_builder.enable("sign_return_address").unwrap(); - // macOS enforces the use of the B key for return addresses. - isa_builder.enable("sign_return_address_with_bkey").unwrap(); - } - } - - // There is no is_s390x_feature_detected macro yet, so for now - // we use getauxval from the libc crate directly. - #[cfg(all(target_arch = "s390x", target_os = "linux"))] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; - const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768; - if (v & HWCAP_S390X_VXRS_EXT2) != 0 { - isa_builder.enable("has_vxrs_ext2").unwrap(); - // There is no separate HWCAP bit for mie2, so assume - // that any machine with vxrs_ext2 also has mie2. - isa_builder.enable("has_mie2").unwrap(); - } - } - - // `is_riscv_feature_detected` is nightly only for now, use - // getauxval from the libc crate directly as a temporary measure. - #[cfg(all(target_arch = "riscv64", target_os = "linux"))] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; - - const HWCAP_RISCV_EXT_A: libc::c_ulong = 1 << (b'a' - b'a'); - const HWCAP_RISCV_EXT_C: libc::c_ulong = 1 << (b'c' - b'a'); - const HWCAP_RISCV_EXT_D: libc::c_ulong = 1 << (b'd' - b'a'); - const HWCAP_RISCV_EXT_F: libc::c_ulong = 1 << (b'f' - b'a'); - const HWCAP_RISCV_EXT_M: libc::c_ulong = 1 << (b'm' - b'a'); - const HWCAP_RISCV_EXT_V: libc::c_ulong = 1 << (b'v' - b'a'); - - if (v & HWCAP_RISCV_EXT_A) != 0 { - isa_builder.enable("has_a").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_C) != 0 { - isa_builder.enable("has_c").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_D) != 0 { - isa_builder.enable("has_d").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_F) != 0 { - isa_builder.enable("has_f").unwrap(); - - // TODO: There doesn't seem to be a bit associated with this extension - // rust enables it with the `f` extension: - // https://github.com/rust-lang/stdarch/blob/790411f93c4b5eada3c23abb4c9a063fb0b24d99/crates/std_detect/src/detect/os/linux/riscv.rs#L43 - isa_builder.enable("has_zicsr").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_M) != 0 { - isa_builder.enable("has_m").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_V) != 0 { - isa_builder.enable("has_v").unwrap(); - } - - // TODO: ZiFencei does not have a bit associated with it - // TODO: Zbkb does not have a bit associated with it - } - - // squelch warnings about unused mut/variables on some platforms. - drop(&mut isa_builder); - drop(infer_native_flags); - - Ok(isa_builder) -} - -#[cfg(test)] -mod tests { - use super::builder; - use cranelift_codegen::isa::CallConv; - use cranelift_codegen::settings; - - #[test] - fn test() { - if let Ok(isa_builder) = builder() { - let flag_builder = settings::builder(); - let isa = isa_builder.finish(settings::Flags::new(flag_builder)).unwrap(); - - if cfg!(all(target_os = "macos", target_arch = "aarch64")) { - assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64); - } else if cfg!(any(unix, target_os = "nebulet")) { - assert_eq!(isa.default_call_conv(), CallConv::SystemV); - } else if cfg!(windows) { - assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall); - } - - if cfg!(target_pointer_width = "64") { - assert_eq!(isa.pointer_bits(), 64); - } else if cfg!(target_pointer_width = "32") { - assert_eq!(isa.pointer_bits(), 32); - } else if cfg!(target_pointer_width = "16") { - assert_eq!(isa.pointer_bits(), 16); - } - } - } -} - -/// Version number of this crate. -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs index 9583cd2ec60..c4a5627e662 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs @@ -113,7 +113,7 @@ impl Writer for WriterRelocate { offset: offset as u32, size, name: DebugRelocName::Symbol(symbol), - addend: addend as i64, + addend, kind: object::RelocationKind::Absolute, }); self.write_udata(0, size) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 7c6fd9f6f1e..3e2e2af9688 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -377,7 +377,7 @@ pub(crate) fn run_aot( }; if tcx.dep_graph.is_fully_enabled() { - for cgu in &*cgus { + for cgu in cgus { tcx.ensure().codegen_unit(cgu.name()); } } @@ -417,7 +417,7 @@ pub(crate) fn run_aot( CguReuse::PreLto => unreachable!(), CguReuse::PostLto => { concurrency_limiter.job_already_done(); - OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu)) + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) } } }) diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 8b5a2da2c59..f6a48e3257b 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -311,7 +311,11 @@ fn dep_symbol_lookup_fn( .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) .unwrap() .1; - for &cnum in &crate_info.used_crates { + // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to + // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib + // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library + // search path. + for &cnum in crate_info.used_crates.iter().rev() { let src = &crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 46c78ce6a1e..a74f8ffa23d 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -125,7 +125,7 @@ pub(crate) fn compile_global_asm( let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); // Assemble `global_asm` - let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); + let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm"); let mut child = Command::new(&config.assembler) .arg("-o") .arg(&global_asm_object_file) diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 6206fbf7dd5..3ba530c040f 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -242,7 +242,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } InlineAsmOperand::Const { ref value } => { - let (const_value, ty) = crate::constant::eval_mir_constant(fx, &*value) + let (const_value, ty) = crate::constant::eval_mir_constant(fx, value) .unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved")); let value = rustc_codegen_ssa::common::asm_const_to_str( fx.tcx, @@ -334,13 +334,13 @@ pub(crate) fn codegen_inline_asm<'tcx>( } CInlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { - outputs.push((asm_gen.stack_slots_output[i].unwrap(), place.clone())); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place)); } } CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => { inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx))); if let Some(out_place) = out_place { - outputs.push((asm_gen.stack_slots_output[i].unwrap(), out_place.clone())); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place)); } } CInlineAsmOperand::Const { value: _ } | CInlineAsmOperand::Symbol { symbol: _ } => {} diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 24f8d5e464e..fe48cac4faf 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -23,7 +23,7 @@ pub(crate) use llvm::codegen_llvm_intrinsic_call; use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::subst::SubstsRef; use rustc_span::symbol::{kw, sym, Symbol}; @@ -252,45 +252,45 @@ fn codegen_float_intrinsic_call<'tcx>( args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, ) -> bool { - let (name, arg_count, ty) = match intrinsic { - sym::expf32 => ("expf", 1, fx.tcx.types.f32), - sym::expf64 => ("exp", 1, fx.tcx.types.f64), - sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32), - sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64), - sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32), - sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64), - sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32), // compiler-builtins - sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64), // compiler-builtins - sym::powf32 => ("powf", 2, fx.tcx.types.f32), - sym::powf64 => ("pow", 2, fx.tcx.types.f64), - sym::logf32 => ("logf", 1, fx.tcx.types.f32), - sym::logf64 => ("log", 1, fx.tcx.types.f64), - sym::log2f32 => ("log2f", 1, fx.tcx.types.f32), - sym::log2f64 => ("log2", 1, fx.tcx.types.f64), - sym::log10f32 => ("log10f", 1, fx.tcx.types.f32), - sym::log10f64 => ("log10", 1, fx.tcx.types.f64), - sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32), - sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64), - sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32), - sym::fmaf64 => ("fma", 3, fx.tcx.types.f64), - sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32), - sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64), - sym::floorf32 => ("floorf", 1, fx.tcx.types.f32), - sym::floorf64 => ("floor", 1, fx.tcx.types.f64), - sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32), - sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64), - sym::truncf32 => ("truncf", 1, fx.tcx.types.f32), - sym::truncf64 => ("trunc", 1, fx.tcx.types.f64), - sym::rintf32 => ("rintf", 1, fx.tcx.types.f32), - sym::rintf64 => ("rint", 1, fx.tcx.types.f64), - sym::roundf32 => ("roundf", 1, fx.tcx.types.f32), - sym::roundf64 => ("round", 1, fx.tcx.types.f64), - sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32), - sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64), - sym::sinf32 => ("sinf", 1, fx.tcx.types.f32), - sym::sinf64 => ("sin", 1, fx.tcx.types.f64), - sym::cosf32 => ("cosf", 1, fx.tcx.types.f32), - sym::cosf64 => ("cos", 1, fx.tcx.types.f64), + let (name, arg_count, ty, clif_ty) = match intrinsic { + sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), + sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), + sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), + sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), + sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), + sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), + sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32, types::F32), // compiler-builtins + sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64, types::F64), // compiler-builtins + sym::powf32 => ("powf", 2, fx.tcx.types.f32, types::F32), + sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), + sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), + sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), + sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), + sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), + sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), + sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), + sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32), + sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), + sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), + sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), + sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), + sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), + sym::floorf64 => ("floor", 1, fx.tcx.types.f64, types::F64), + sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32, types::F32), + sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), + sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), + sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), + sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), + sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), + sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), + sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32), + sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64), + sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), + sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), + sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), + sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), _ => return false, }; @@ -301,15 +301,19 @@ fn codegen_float_intrinsic_call<'tcx>( let (a, b, c); let args = match args { [x] => { - a = [codegen_operand(fx, x)]; + a = [codegen_operand(fx, x).load_scalar(fx)]; &a as &[_] } [x, y] => { - b = [codegen_operand(fx, x), codegen_operand(fx, y)]; + b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)]; &b } [x, y, z] => { - c = [codegen_operand(fx, x), codegen_operand(fx, y), codegen_operand(fx, z)]; + c = [ + codegen_operand(fx, x).load_scalar(fx), + codegen_operand(fx, y).load_scalar(fx), + codegen_operand(fx, z).load_scalar(fx), + ]; &c } _ => unreachable!(), @@ -318,15 +322,10 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { sym::fmaf32 | sym::fmaf64 => { - let a = args[0].load_scalar(fx); - let b = args[1].load_scalar(fx); - let c = args[2].load_scalar(fx); - CValue::by_val(fx.bcx.ins().fma(a, b, c), layout) + CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { - let a = args[0].load_scalar(fx); - let b = args[1].load_scalar(fx); - CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout) + CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) } sym::fabsf32 | sym::fabsf64 @@ -336,21 +335,29 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf64 | sym::truncf32 | sym::truncf64 => { - let a = args[0].load_scalar(fx); - let val = match intrinsic { - sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a), - sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a), - sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a), - sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a), + sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), _ => unreachable!(), }; CValue::by_val(val, layout) } + // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. - _ => fx.easy_call(name, &args, ty), + sym::powif32 | sym::powif64 => { + let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), AbiParam::new(types::I32)]; + let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; + CValue::by_val(ret_val, fx.layout_of(ty)) + } + _ => { + let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); + let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; + CValue::by_val(ret_val, fx.layout_of(ty)) + } }; ret.write_cvalue(fx, res); @@ -385,7 +392,7 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().debugtrap(); } - sym::copy | sym::copy_nonoverlapping => { + sym::copy => { intrinsic_args!(fx, args => (src, dst, count); intrinsic); let src = src.load_scalar(fx); let dst = dst.load_scalar(fx); @@ -397,13 +404,8 @@ fn codegen_regular_intrinsic_call<'tcx>( let byte_amount = if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; - if intrinsic == sym::copy_nonoverlapping { - // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); - } else { - // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); - } + // FIXME emit_small_memmove + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => { // NOTE: the volatile variants have src and dst swapped @@ -643,26 +645,25 @@ fn codegen_regular_intrinsic_call<'tcx>( if do_panic { let layout = fx.layout_of(ty); - - with_no_trimmed_paths!({ - crate::base::codegen_panic_nounwind( - fx, - &if layout.abi.is_uninhabited() { - format!("attempted to instantiate uninhabited type `{}`", layout.ty) - } else if requirement == ValidityRequirement::Zero { + let msg_str = with_no_visible_paths!({ + with_no_trimmed_paths!({ + if layout.abi.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{}`", ty) + } else if intrinsic == sym::assert_zero_valid { format!( "attempted to zero-initialize type `{}`, which is invalid", - layout.ty + ty ) } else { format!( "attempted to leave type `{}` uninitialized, which is invalid", - layout.ty + ty ) - }, - source_info, - ) + } + }) }); + crate::base::codegen_panic_nounwind(fx, &msg_str, source_info); return; } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index a1d63acfb61..034b4e8072c 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -279,9 +279,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); let trap_block = fx.bcx.create_block(); let true_ = fx.bcx.ins().iconst(types::I8, 1); - fx.bcx.ins().brnz(true_, trap_block, &[]); let ret_block = fx.get_block(target); - fx.bcx.ins().jump(ret_block, &[]); + fx.bcx.ins().brif(true_, trap_block, &[], ret_block, &[]); fx.bcx.switch_to_block(trap_block); crate::trap::trap_unimplemented( fx, @@ -825,8 +824,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let next = fx.bcx.create_block(); let res_lane = fx.bcx.append_block_param(next, lane_clif_ty); - fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); - fx.bcx.ins().jump(if_disabled, &[]); + fx.bcx.ins().brif(mask_lane, if_enabled, &[], if_disabled, &[]); fx.bcx.seal_block(if_enabled); fx.bcx.seal_block(if_disabled); @@ -864,8 +862,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let if_enabled = fx.bcx.create_block(); let next = fx.bcx.create_block(); - fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); - fx.bcx.ins().jump(next, &[]); + fx.bcx.ins().brif(mask_lane, if_enabled, &[], next, &[]); fx.bcx.seal_block(if_enabled); fx.bcx.switch_to_block(if_enabled); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 80ce3dc9328..bed79859f51 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -57,8 +57,6 @@ mod compiler_builtins; mod concurrency_limiter; mod config; mod constant; -// FIXME revert back to the external crate with Cranelift 0.93 -mod cranelift_native; mod debuginfo; mod discriminant; mod driver; @@ -251,7 +249,7 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple { } } -fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::TargetIsa + 'static> { +fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn isa::TargetIsa + 'static> { use target_lexicon::BinaryFormat; let target_triple = crate::target_triple(sess); @@ -285,14 +283,17 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar } } - if let target_lexicon::Architecture::Aarch64(_) | target_lexicon::Architecture::X86_64 = - target_triple.architecture + if let target_lexicon::Architecture::Aarch64(_) + | target_lexicon::Architecture::Riscv64(_) + | target_lexicon::Architecture::X86_64 = target_triple.architecture { - // Windows depends on stack probes to grow the committed part of the stack + // Windows depends on stack probes to grow the committed part of the stack. + // On other platforms it helps prevents stack smashing. flags_builder.enable("enable_probestack").unwrap(); flags_builder.set("probestack_strategy", "inline").unwrap(); } else { - // __cranelift_probestack is not provided and inline stack probes are only supported on AArch64 and x86_64 + // __cranelift_probestack is not provided and inline stack probes are only supported on + // AArch64, Riscv64 and x86_64. flags_builder.set("enable_probestack", "false").unwrap(); } diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index be908df83e8..205411e8c27 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -28,7 +28,7 @@ pub(crate) fn maybe_create_entry_wrapper( if main_def_id.is_local() { let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); - if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() { + if !is_jit && module.get_name(tcx.symbol_name(instance).name).is_none() { return; } } else if !is_primary_cgu { diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index c058ece96d8..1357b7be1e0 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -170,14 +170,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( in_lhs: CValue<'tcx>, in_rhs: CValue<'tcx>, ) -> CValue<'tcx> { - if bin_op != BinOp::Shl && bin_op != BinOp::Shr { - assert_eq!( - in_lhs.layout().ty, - in_rhs.layout().ty, - "checked int binop requires lhs and rhs of same type" - ); - } - let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); @@ -271,21 +263,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( _ => unreachable!("invalid non-integer type {}", ty), } } - BinOp::Shl => { - let val = fx.bcx.ins().ishl(lhs, rhs); - let ty = fx.bcx.func.dfg.value_type(val); - let max_shift = i64::from(ty.bits()) - 1; - let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); - (val, has_overflow) - } - BinOp::Shr => { - let val = - if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) }; - let ty = fx.bcx.func.dfg.value_type(val); - let max_shift = i64::from(ty.bits()) - 1; - let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); - (val, has_overflow) - } _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs), }; @@ -347,12 +324,20 @@ pub(crate) fn codegen_float_binop<'tcx>( BinOp::Mul => b.fmul(lhs, rhs), BinOp::Div => b.fdiv(lhs, rhs), BinOp::Rem => { - let name = match in_lhs.layout().ty.kind() { - ty::Float(FloatTy::F32) => "fmodf", - ty::Float(FloatTy::F64) => "fmod", + let (name, ty) = match in_lhs.layout().ty.kind() { + ty::Float(FloatTy::F32) => ("fmodf", types::F32), + ty::Float(FloatTy::F64) => ("fmod", types::F64), _ => bug!(), }; - return fx.easy_call(name, &[in_lhs, in_rhs], in_lhs.layout().ty); + + let ret_val = fx.lib_call( + name, + vec![AbiParam::new(ty), AbiParam::new(ty)], + vec![AbiParam::new(ty)], + &[lhs, rhs], + )[0]; + + return CValue::by_val(ret_val, in_lhs.layout()); } BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { let fltcc = match bin_op { diff --git a/compiler/rustc_codegen_cranelift/src/pointer.rs b/compiler/rustc_codegen_cranelift/src/pointer.rs index 31d827f83bf..b60e56720ed 100644 --- a/compiler/rustc_codegen_cranelift/src/pointer.rs +++ b/compiler/rustc_codegen_cranelift/src/pointer.rs @@ -30,11 +30,6 @@ impl Pointer { Pointer { base: PointerBase::Stack(stack_slot), offset: Offset32::new(0) } } - pub(crate) fn const_addr(fx: &mut FunctionCx<'_, '_, '_>, addr: i64) -> Self { - let addr = fx.bcx.ins().iconst(fx.pointer_type, addr); - Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) } - } - pub(crate) fn dangling(align: Align) -> Self { Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index a7af162687c..e0a081c9d49 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -245,7 +245,7 @@ pub(crate) fn write_clif_file( for flag in isa.flags().iter() { writeln!(file, "set {}", flag)?; } - write!(file, "target {}", isa.triple().architecture.to_string())?; + write!(file, "target {}", isa.triple().architecture)?; for isa_flag in isa.isa_flags().iter() { write!(file, " {}", isa_flag)?; } diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index a0745582d66..ecf187a0b0f 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -28,9 +28,7 @@ pub(crate) fn unsized_info<'tcx>( ( &ty::Dynamic(ref data_a, _, src_dyn_kind), &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) => { - assert_eq!(src_dyn_kind, target_dyn_kind); - + ) if src_dyn_kind == target_dyn_kind => { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { @@ -55,7 +53,7 @@ pub(crate) fn unsized_info<'tcx>( old_info } } - (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), + (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index cc1edaa97d8..58e0a498292 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use cranelift_codegen::ir::immediates::Offset32; +use cranelift_codegen::ir::{InstructionData, Opcode}; fn codegen_field<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -457,6 +458,7 @@ impl<'tcx> CPlace<'tcx> { } } + #[track_caller] pub(crate) fn to_ptr(self) -> Pointer { match self.to_ptr_maybe_unsized() { (ptr, None) => ptr, @@ -464,6 +466,7 @@ impl<'tcx> CPlace<'tcx> { } } + #[track_caller] pub(crate) fn to_ptr_maybe_unsized(self) -> (Pointer, Option<Value>) { match self.inner { CPlaceInner::Addr(ptr, extra) => (ptr, extra), @@ -787,7 +790,36 @@ impl<'tcx> CPlace<'tcx> { index: Value, ) -> CPlace<'tcx> { let (elem_layout, ptr) = match self.layout().ty.kind() { - ty::Array(elem_ty, _) => (fx.layout_of(*elem_ty), self.to_ptr()), + ty::Array(elem_ty, _) => { + let elem_layout = fx.layout_of(*elem_ty); + match self.inner { + CPlaceInner::Var(local, var) => { + // This is a hack to handle `vector_val.0[1]`. It doesn't allow dynamic + // indexing. + let lane_idx = match fx.bcx.func.dfg.insts + [fx.bcx.func.dfg.value_def(index).unwrap_inst()] + { + InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => imm, + _ => bug!( + "Dynamic indexing into a vector type is not supported: {self:?}[{index}]" + ), + }; + return CPlace { + inner: CPlaceInner::VarLane( + local, + var, + lane_idx.bits().try_into().unwrap(), + ), + layout: elem_layout, + }; + } + CPlaceInner::Addr(addr, None) => (elem_layout, addr), + CPlaceInner::Addr(_, Some(_)) + | CPlaceInner::VarPair(_, _, _) + | CPlaceInner::VarLane(_, _, _) => bug!("Can't index into {self:?}"), + } + // FIXME use VarLane in case of Var with simd type + } ty::Slice(elem_ty) => (fx.layout_of(*elem_ty), self.to_ptr_maybe_unsized().0), _ => bug!("place_index({:?})", self.layout().ty), }; diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index f04fb82de8c..b7bfd8fd395 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -43,10 +43,29 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) - pub(crate) fn get_ptr_and_method_ref<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - arg: CValue<'tcx>, + mut arg: CValue<'tcx>, idx: usize, ) -> (Pointer, Value) { let (ptr, vtable) = 'block: { + if let Abi::Scalar(_) = arg.layout().abi { + 'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() + && !arg.layout().ty.is_region_ptr() + { + for i in 0..arg.layout().fields.count() { + let field = arg.value_field(fx, mir::Field::new(i)); + if !field.layout().is_zst() { + // we found the one non-zero-sized field that is allowed + // now find *its* non-zero-sized field, or stop if it's a + // pointer + arg = field; + continue 'descend_newtypes; + } + } + + bug!("receiver has no non-zero-sized fields {:?}", arg); + } + } + if let ty::Ref(_, ty, _) = arg.layout().ty.kind() { if ty.is_dyn_star() { let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 3d856986fb4..13c4fa132d8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -663,17 +663,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; bx.checked_binop(oop, input_ty, lhs, rhs) } - mir::BinOp::Shl | mir::BinOp::Shr => { - let lhs_llty = bx.cx().val_ty(lhs); - let rhs_llty = bx.cx().val_ty(rhs); - let invert_mask = common::shift_mask_val(bx, lhs_llty, rhs_llty, true); - let outer_bits = bx.and(rhs, invert_mask); - - let of = bx.icmp(IntPredicate::IntNE, outer_bits, bx.cx().const_null(rhs_llty)); - let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty); - - (val, of) - } _ => bug!("Operator `{:?}` is not a checkable operator", op), }; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 49b1e6d967c..e0939d1d1ba 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -564,15 +564,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - Shl | Shr => { - for x in [a, b] { - check_kinds!( - x, - "Cannot perform checked shift on non-integer type {:?}", - ty::Uint(..) | ty::Int(..) - ) - } - } _ => self.fail(location, format!("There is no checked version of {:?}", op)), } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0416.md b/compiler/rustc_error_codes/src/error_codes/E0416.md index 7bc316dafc5..8c0edcee521 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0416.md +++ b/compiler/rustc_error_codes/src/error_codes/E0416.md @@ -23,6 +23,6 @@ Or maybe did you mean to unify? Consider using a guard: # let (A, B, C) = (1, 2, 3); match (A, B, C) { (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } - (y, z, see) => { /* A and B unequal; do another thing */ } + (y, z, see) => { /* A and B not equal; do another thing */ } } ``` diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 47a8b4bc488..a07cb65170d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -367,7 +367,7 @@ impl LockstepIterSize { /// /// Example: `$($($x $y)+*);+` -- we need to make sure that `x` and `y` repeat the same amount as /// each other at the given depth when the macro was invoked. If they don't it might mean they were -/// declared at unequal depths or there was a compile bug. For example, if we have 3 repetitions of +/// declared at depths which weren't equal or there was a compiler bug. For example, if we have 3 repetitions of /// the outer sequence and 4 repetitions of the inner sequence for `x`, we should have the same for /// `y`; otherwise, we can't transcribe them both at the given depth. fn lockstep_iter_size( diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 8ceb176491b..3c4fc9cb530 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -404,8 +404,12 @@ impl DefPathData { match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + // We use this name when collecting `ModChild`s. + // FIXME this could probably be removed with some refactoring to the name resolver. + ImplTraitAssocTy => Some(kw::Empty), + Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst - | ImplTrait | ImplTraitAssocTy => None, + | ImplTrait => None, } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3cd4c4afe86..f830269b45d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1440,6 +1440,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.associated_items(pred.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none()) .map(|item| item.def_id), ); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 20b6561f8b2..8c364a4f3b2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -363,6 +363,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), + sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), + sym::discriminant_value => { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5e8f69677cf..0e1cf3e6c6a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::{self, RegionResolutionError}; +use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -235,7 +235,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef use rustc_type_ir::sty::TyKind::*; match (source.kind(), target.kind()) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) - if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {} + if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok() + && mutbl_a == *mutbl_b => {} (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (), (&Adt(def_a, substs_a), &Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => @@ -278,7 +279,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } - if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { + if let Ok(ok) = + infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) + { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ @@ -504,7 +507,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // we may have to evaluate constraint // expressions in the course of execution.) // See e.g., #41936. - if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) { + if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) { if ok.obligations.is_empty() { return None; } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index e9963e67741..465ae047de3 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1427,25 +1427,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let ResolvedArg::LateBound(..) = def && crossed_anon_const { let use_span = self.tcx.hir().span(hir_id); let def_span = self.tcx.def_span(param_def_id); - match self.tcx.def_kind(param_def_id) { + let guar = match self.tcx.def_kind(param_def_id) { DefKind::ConstParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const { use_span, def_span, - }); + }) } DefKind::TyParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type { use_span, def_span, - }); + }) } _ => unreachable!(), - } - return; + }; + self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + } else { + self.map.defs.insert(hir_id, def); } - - self.map.defs.insert(hir_id, def); return; } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 62abcbbdc9f..08786fe9b1e 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::Node; -use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_macros::fluent_messages; use rustc_middle::middle; use rustc_middle::ty::query::Providers; @@ -165,7 +165,7 @@ fn require_same_types<'tcx>( ) -> bool { let infcx = &tcx.infer_ctxt().build(); let param_env = ty::ParamEnv::empty(); - let errors = match infcx.at(cause, param_env).eq(expected, actual) { + let errors = match infcx.at(cause, param_env).eq(DefineOpaqueTypes::No, expected, actual) { Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 773ac0e40c5..6becf4892ac 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime}; use rustc_infer::infer::{InferOk, InferResult}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; @@ -563,10 +563,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // Check that E' = S'. let cause = self.misc(hir_ty.span); - let InferOk { value: (), obligations } = self - .at(&cause, self.param_env) - .define_opaque_types(true) - .eq(*expected_ty, supplied_ty)?; + let InferOk { value: (), obligations } = self.at(&cause, self.param_env).eq( + DefineOpaqueTypes::Yes, + *expected_ty, + supplied_ty, + )?; all_obligations.extend(obligations); } @@ -576,10 +577,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_sig.output(), ); let cause = &self.misc(decl.output.span()); - let InferOk { value: (), obligations } = self - .at(cause, self.param_env) - .define_opaque_types(true) - .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; + let InferOk { value: (), obligations } = self.at(cause, self.param_env).eq( + DefineOpaqueTypes::Yes, + expected_sigs.liberated_sig.output(), + supplied_output_ty, + )?; all_obligations.extend(obligations); let inputs = inputs.into_iter().map(|ty| self.resolve_vars_if_possible(ty)); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 00b86890b33..3d6274ede81 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -45,7 +45,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{Coercion, InferOk, InferResult}; +use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ @@ -143,11 +143,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { - let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true); + let at = self.at(&self.cause, self.fcx.param_env); if self.use_lub { - at.lub(b, a) + at.lub(DefineOpaqueTypes::Yes, b, a) } else { - at.sup(b, a) + at.sup(DefineOpaqueTypes::Yes, b, a) .map(|InferOk { value: (), obligations }| InferOk { value: a, obligations }) } }) @@ -175,7 +175,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // so this will have the side-effect of making sure we have no ambiguities // due to `[type error]` and `_` not coercing together. let _ = self.commit_if_ok(|_| { - self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b) + self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b) }); return success(vec![], self.fcx.tcx.ty_error(guar), vec![]); } @@ -1101,9 +1101,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::FnDef(..), ty::FnDef(..)) => { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. - match self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - { + match self.commit_if_ok(|_| { + self.at(cause, self.param_env).lub( + DefineOpaqueTypes::No, + prev_ty, + new_ty, + ) + }) { // We have a LUB of prev_ty and new_ty, just return it. Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)), Err(_) => { @@ -1153,7 +1157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = self .at(cause, self.param_env) .trace(prev_ty, new_ty) - .lub(a_sig, b_sig) + .lub(DefineOpaqueTypes::No, a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. @@ -1237,7 +1241,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) + .commit_if_ok(|_| { + self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty) + }) .map(|ok| self.register_infer_ok_obligations(ok)); } } @@ -1248,8 +1254,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(e) = first_error { Err(e) } else { - self.commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - .map(|ok| self.register_infer_ok_obligations(ok)) + self.commit_if_ok(|_| { + self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty) + }) + .map(|ok| self.register_infer_ok_obligations(ok)) } } Ok(ok) => { @@ -1487,8 +1495,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { assert!(expression_ty.is_unit(), "if let hack without unit type"); fcx.at(cause, fcx.param_env) // needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs - .define_opaque_types(true) - .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty()) + .eq_exp( + DefineOpaqueTypes::Yes, + label_expression_as_expected, + expression_ty, + self.merged_ty(), + ) .map(|infer_ok| { fcx.register_infer_ok_obligations(infer_ok); expression_ty diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 7ba57b3b7a2..f65f16e317d 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -8,7 +8,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; -use rustc_infer::infer::InferOk; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.annotate_expected_due_to_let_ty(err, expr, error); self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error); self.note_type_is_not_clone(err, expected, expr_ty, expr); - self.note_internal_mutation_in_method(err, expr, expected, expr_ty); + self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty); self.check_for_range_as_method_call(err, expr, expr_ty, expected); self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected); self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty); @@ -113,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - match self.at(cause, self.param_env).define_opaque_types(true).sup(expected, actual) { + match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - match self.at(cause, self.param_env).define_opaque_types(true).eq(expected, actual) { + match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7fc4ccb04ee..afef331ec1d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -36,6 +36,7 @@ use rustc_hir_analysis::astconv::AstConv as _; use rustc_hir_analysis::check::ty_kind_suggestion; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::InferOk; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability; @@ -1683,7 +1684,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, substs); let cause = self.misc(base_expr.span); - match self.at(&cause, self.param_env).sup(target_ty, fru_ty) { + match self.at(&cause, self.param_env).sup( + DefineOpaqueTypes::No, + target_ty, + fru_ty, + ) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 4720306e159..e539693402a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -19,7 +19,7 @@ use rustc_hir_analysis::astconv::{ }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc_infer::infer::InferResult; +use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = self.tcx.hir().body(body_id).value.span; let ok = self .at(&self.misc(span), self.param_env) - .eq(interior, witness) + .eq(DefineOpaqueTypes::No, interior, witness) .expect("Failed to unify generator interior type"); let mut obligations = ok.obligations; @@ -950,44 +950,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, - expected: Ty<'tcx>, + expected: Option<Ty<'tcx>>, found: Ty<'tcx>, ) { if found != self.tcx.types.unit { return; } - if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind { - if self - .typeck_results + + let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind else { + return; + }; + + let rcvr_has_the_expected_type = self + .typeck_results + .borrow() + .expr_ty_adjusted_opt(rcvr) + .and_then(|ty| expected.map(|expected_ty| expected_ty.peel_refs() == ty.peel_refs())) + .unwrap_or(false); + + let prev_call_mutates_and_returns_unit = || { + self.typeck_results .borrow() - .expr_ty_adjusted_opt(rcvr) - .map_or(true, |ty| expected.peel_refs() != ty.peel_refs()) - { - return; - } - let mut sp = MultiSpan::from_span(path_segment.ident.span); - sp.push_span_label( - path_segment.ident.span, - format!( - "this call modifies {} in-place", - match rcvr.kind { - ExprKind::Path(QPath::Resolved( - None, - hir::Path { segments: [segment], .. }, - )) => format!("`{}`", segment.ident), - _ => "its receiver".to_string(), - } - ), - ); + .type_dependent_def_id(expr.hir_id) + .map(|def_id| self.tcx.fn_sig(def_id).skip_binder().skip_binder()) + .and_then(|sig| sig.inputs_and_output.split_last()) + .map(|(output, inputs)| { + output.is_unit() + && inputs + .get(0) + .and_then(|self_ty| self_ty.ref_mutability()) + .map_or(false, rustc_ast::Mutability::is_mut) + }) + .unwrap_or(false) + }; + + if !(rcvr_has_the_expected_type || prev_call_mutates_and_returns_unit()) { + return; + } + + let mut sp = MultiSpan::from_span(path_segment.ident.span); + sp.push_span_label( + path_segment.ident.span, + format!( + "this call modifies {} in-place", + match rcvr.kind { + ExprKind::Path(QPath::Resolved( + None, + hir::Path { segments: [segment], .. }, + )) => format!("`{}`", segment.ident), + _ => "its receiver".to_string(), + } + ), + ); + + let modifies_rcvr_note = + format!("method `{}` modifies its receiver in-place", path_segment.ident); + if rcvr_has_the_expected_type { sp.push_span_label( rcvr.span, "you probably want to use this value after calling the method...", ); + err.span_note(sp, &modifies_rcvr_note); + err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident)); + } else if let ExprKind::MethodCall(..) = rcvr.kind { err.span_note( sp, - &format!("method `{}` modifies its receiver in-place", path_segment.ident), + modifies_rcvr_note.clone() + ", it is not meant to be used in method chains.", ); - err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident)); + } else { + err.span_note(sp, &modifies_rcvr_note); } } @@ -1310,7 +1341,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This also occurs for an enum variant on a type alias. let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).subst(tcx, substs)); let self_ty = self.normalize(span, self_ty); - match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) { + match self.at(&self.misc(span), self.param_env).eq( + DefineOpaqueTypes::No, + impl_ty, + self_ty, + ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { self.tcx.sess.delay_span_bug( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ea54b76bdec..7064ff65384 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -24,8 +24,8 @@ use rustc_hir_analysis::structured_errors::StructuredDiagnostic; use rustc_index::vec::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::InferOk; use rustc_infer::infer::TypeTrace; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty}; @@ -301,9 +301,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 3. Check if the formal type is a supertype of the checked one // and register any such obligations for future type checks - let supertype_error = self - .at(&self.misc(provided_arg.span), self.param_env) - .sup(formal_input_ty, coerced_ty); + let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup( + DefineOpaqueTypes::No, + formal_input_ty, + coerced_ty, + ); let subtyping_error = match supertype_error { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); @@ -585,7 +587,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Using probe here, since we don't want this subtyping to affect inference. let subtyping_error = self.probe(|_| { - self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err() + self.at(&self.misc(arg_span), self.param_env) + .sup(DefineOpaqueTypes::No, formal_input_ty, coerced_ty) + .err() }); // Same as above: if either the coerce type or the checked type is an error type, diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 2e41c2041f8..9ecc870a70d 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -13,7 +13,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; -use rustc_infer::infer::RegionVariableOrigin; +use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin}; use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt}; @@ -327,7 +327,11 @@ pub fn resolve_interior<'a, 'tcx>( ); // Unify the type variable inside the generator with the new witness - match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) { + match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq( + DefineOpaqueTypes::No, + interior, + witness, + ) { Ok(ok) => fcx.register_infer_ok_obligations(ok), _ => bug!("failed to relate {interior} and {witness}"), } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 169f128e0a0..a0aa43deadc 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -8,7 +8,7 @@ use rustc_hir_analysis::astconv::generics::{ check_generic_arg_count_for_call, create_substs_for_generic_args, }; use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; -use rustc_infer::infer::{self, InferOk}; +use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; @@ -478,7 +478,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { substs, })), ); - match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { + match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3254a930342..8f31a79e7b3 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -13,6 +13,7 @@ use rustc_hir_analysis::astconv::InferCtxtExt as _; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::TreatProjections; @@ -930,7 +931,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let Some(self_ty) = self_ty { if self .at(&ObligationCause::dummy(), self.param_env) - .sup(fty.inputs()[0], self_ty) + .sup(DefineOpaqueTypes::No, fty.inputs()[0], self_ty) .is_err() { return false; @@ -1436,9 +1437,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { - let _ = self - .at(&ObligationCause::dummy(), self.param_env) - .sup(candidate.xform_self_ty, self_ty); + let _ = self.at(&ObligationCause::dummy(), self.param_env).sup( + DefineOpaqueTypes::No, + candidate.xform_self_ty, + self_ty, + ); match self.select_trait_candidate(trait_ref) { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point @@ -1465,10 +1468,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.probe(|_| { // First check that the self type can be related. - let sub_obligations = match self - .at(&ObligationCause::dummy(), self.param_env) - .sup(probe.xform_self_ty, self_ty) - { + let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup( + DefineOpaqueTypes::No, + probe.xform_self_ty, + self_ty, + ) { Ok(InferOk { obligations, value: () }) => obligations, Err(err) => { debug!("--> cannot relate self-types {:?}", err); @@ -1683,7 +1687,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let ProbeResult::Match = result && self .at(&ObligationCause::dummy(), self.param_env) - .sup(return_ty, xform_ret_ty) + .sup(DefineOpaqueTypes::No, return_ty, xform_ret_ty) .is_err() { result = ProbeResult::BadReturnType; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7055d9257ec..50f2b71250c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -416,6 +416,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); probe.is_ok() }); + + self.note_internal_mutation_in_method( + &mut err, + rcvr_expr, + expected.to_option(&self), + rcvr_ty, + ); } let mut custom_span_label = false; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 7d9bae735e5..0c8854e962a 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -30,16 +30,20 @@ use super::*; use rustc_middle::ty::relate::{Relate, TypeRelation}; use rustc_middle::ty::{Const, ImplSubject}; +/// Whether we should define opaque types or just treat them opaquely. +/// +/// Currently only used to prevent predicate matching from matching anything +/// against opaque types. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum DefineOpaqueTypes { + Yes, + No, +} + pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub cause: &'a ObligationCause<'tcx>, pub param_env: ty::ParamEnv<'tcx>, - /// Whether we should define opaque types - /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, } pub struct Trace<'a, 'tcx> { @@ -55,7 +59,7 @@ impl<'tcx> InferCtxt<'tcx> { cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> At<'a, 'tcx> { - At { infcx: self, cause, param_env, define_opaque_types: false } + At { infcx: self, cause, param_env } } /// Forks the inference context, creating a new inference context with the same inference @@ -84,7 +88,6 @@ impl<'tcx> InferCtxt<'tcx> { pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -93,33 +96,21 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { } impl<'a, 'tcx> At<'a, 'tcx> { - pub fn define_opaque_types(self, define_opaque_types: bool) -> Self { - Self { define_opaque_types, ..self } - } - - /// Hacky routine for equating two impl headers in coherence. - pub fn eq_impl_headers( - self, - expected: &ty::ImplHeader<'tcx>, - actual: &ty::ImplHeader<'tcx>, - ) -> InferResult<'tcx, ()> { - debug!("eq_impl_header({:?} = {:?})", expected, actual); - match (expected.trait_ref, actual.trait_ref) { - (Some(a_ref), Some(b_ref)) => self.eq(a_ref, b_ref), - (None, None) => self.eq(expected.self_ty, actual.self_ty), - _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), - } - } - /// Makes `a <: b`, where `a` may or may not be expected. /// /// See [`At::trace_exp`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sub_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> + pub fn sub_exp<T>( + self, + define_opaque_types: DefineOpaqueTypes, + a_is_expected: bool, + a: T, + b: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).sub(a, b) + self.trace_exp(a_is_expected, a, b).sub(define_opaque_types, a, b) } /// Makes `actual <: expected`. For example, if type-checking a @@ -129,54 +120,81 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sup<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn sup<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.sub_exp(false, actual, expected) + self.sub_exp(define_opaque_types, false, actual, expected) } /// Makes `expected <: actual`. /// /// See [`At::trace`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sub<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn sub<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.sub_exp(true, expected, actual) + self.sub_exp(define_opaque_types, true, expected, actual) } /// Makes `expected <: actual`. /// /// See [`At::trace_exp`] and [`Trace::eq`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn eq_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> + pub fn eq_exp<T>( + self, + define_opaque_types: DefineOpaqueTypes, + a_is_expected: bool, + a: T, + b: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).eq(a, b) + self.trace_exp(a_is_expected, a, b).eq(define_opaque_types, a, b) } /// Makes `expected <: actual`. /// /// See [`At::trace`] and [`Trace::eq`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn eq<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn eq<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq(expected, actual) + self.trace(expected, actual).eq(define_opaque_types, expected, actual) } - pub fn relate<T>(self, expected: T, variance: ty::Variance, actual: T) -> InferResult<'tcx, ()> + pub fn relate<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + variance: ty::Variance, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { match variance { - ty::Variance::Covariant => self.sub(expected, actual), - ty::Variance::Invariant => self.eq(expected, actual), - ty::Variance::Contravariant => self.sup(expected, actual), + ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual), + ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual), + ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual), // We could make this make sense but it's not readily // exposed and I don't feel like dealing with it. Note @@ -195,11 +213,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::lub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T> + pub fn lub<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { - self.trace(expected, actual).lub(expected, actual) + self.trace(expected, actual).lub(define_opaque_types, expected, actual) } /// Computes the greatest-lower-bound, or mutual subtype, of two @@ -208,11 +231,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::glb`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn glb<T>(self, expected: T, actual: T) -> InferResult<'tcx, T> + pub fn glb<T>( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { - self.trace(expected, actual).glb(expected, actual) + self.trace(expected, actual).glb(define_opaque_types, expected, actual) } /// Sets the "trace" values that will be used for @@ -233,7 +261,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let trace = ToTrace::to_trace(self.infcx.tcx, self.cause, a_is_expected, a, b); + let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b); Trace { at: self, trace, a_is_expected } } } @@ -242,13 +270,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a <: b` where `a` may or may not be expected (if /// `a_is_expected` is true, then `a` is expected). #[instrument(skip(self), level = "debug")] - pub fn sub<T>(self, a: T, b: T) -> InferResult<'tcx, ()> + pub fn sub<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .sub(a_is_expected) .relate(a, b) @@ -259,13 +287,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a == b`; the expectation is set by the call to /// `trace()`. #[instrument(skip(self), level = "debug")] - pub fn eq<T>(self, a: T, b: T) -> InferResult<'tcx, ()> + pub fn eq<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .equate(a_is_expected) .relate(a, b) @@ -274,13 +302,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - pub fn lub<T>(self, a: T, b: T) -> InferResult<'tcx, T> + pub fn lub<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .lub(a_is_expected) .relate(a, b) @@ -289,13 +317,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - pub fn glb<T>(self, a: T, b: T) -> InferResult<'tcx, T> + pub fn glb<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .glb(a_is_expected) .relate(a, b) @@ -306,7 +334,6 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -314,10 +341,10 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { ) -> TypeTrace<'tcx> { match (a, b) { (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, trait_ref_a, trait_ref_b) + ToTrace::to_trace(cause, a_is_expected, trait_ref_a, trait_ref_b) } (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, ty_a, ty_b) + ToTrace::to_trace(cause, a_is_expected, ty_a, ty_b) } (ImplSubject::Trait(_), ImplSubject::Inherent(_)) | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => { @@ -329,7 +356,6 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -344,7 +370,6 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -356,7 +381,6 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { impl<'tcx> ToTrace<'tcx> for Const<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -371,7 +395,6 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -399,7 +422,6 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -411,7 +433,6 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -426,7 +447,6 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -441,24 +461,17 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, b: Self, ) -> TypeTrace<'tcx> { - let a_ty = tcx.mk_projection(a.def_id, a.substs); - let b_ty = tcx.mk_projection(b.def_id, b.substs); - TypeTrace { - cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())), - } + TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) } } } impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 436d29c2449..156a7e68ed1 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -14,7 +14,7 @@ use crate::infer::canonical::{ }; use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; +use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt}; @@ -510,7 +510,7 @@ impl<'tcx> InferCtxt<'tcx> { let b = substitute_value(self.tcx, &result_subst, b); debug!(?a, ?b, "constrain opaque type"); obligations - .extend(self.at(cause, param_env).define_opaque_types(true).eq(a, b)?.obligations); + .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -603,8 +603,11 @@ impl<'tcx> InferCtxt<'tcx> { match (value1.unpack(), value2.unpack()) { (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env) + .eq(DefineOpaqueTypes::Yes, v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2)) if re1.is_erased() && re2.is_erased() => @@ -612,11 +615,14 @@ impl<'tcx> InferCtxt<'tcx> { // no action needed } (GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env) + .eq(DefineOpaqueTypes::Yes, v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { - let ok = self.at(cause, param_env).eq(v1, v2)?; + let ok = self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, v1, v2)?; obligations.extend(ok.into_obligations()); } _ => { diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a2332797e86..bb6fdd2ffc2 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -27,7 +27,7 @@ use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; -use super::{InferCtxt, MiscVariable, TypeTrace}; +use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; @@ -52,12 +52,7 @@ pub struct CombineFields<'infcx, 'tcx> { pub cause: Option<ty::relate::Cause>, pub param_env: ty::ParamEnv<'tcx>, pub obligations: PredicateObligations<'tcx>, - /// Whether we should define opaque types - /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, + pub define_opaque_types: DefineOpaqueTypes, } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 54a62326ef7..c92a74b6241 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -1,3 +1,4 @@ +use crate::infer::DefineOpaqueTypes; use crate::traits::PredicateObligations; use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir}; @@ -110,7 +111,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + && def_id.is_local() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 8a2b800af0e..ac4986a577c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1568,6 +1568,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { (false, Mismatch::Fixed("trait")) } + ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => { + (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id))) + } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), }; let Some(vals) = self.values_str(values) else { @@ -2124,6 +2127,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { match values { infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Terms(exp_found) => self.expected_found_str_term(exp_found), + infer::Aliases(exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 49df393d83b..5c12351226a 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefineOpaqueTypes { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index f377ac1d19e..7f4c141b97a 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -19,7 +19,7 @@ use super::combine::ObligationEmittingRelation; use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::InferCtxt; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::ObligationCause; use rustc_middle::ty::relate::RelateResult; @@ -36,7 +36,7 @@ pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> { fn cause(&self) -> &ObligationCause<'tcx>; - fn define_opaque_types(&self) -> bool; + fn define_opaque_types(&self) -> DefineOpaqueTypes; // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. @@ -110,7 +110,7 @@ where ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if this.define_opaque_types() && def_id.is_local() => + if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() => { this.register_obligations( infcx diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index c871ccb21f8..dbef42db8f1 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefineOpaqueTypes { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4a834957959..96e7c095d34 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,3 +1,4 @@ +pub use self::at::DefineOpaqueTypes; pub use self::freshen::TypeFreshener; pub use self::lexical_region_resolve::RegionResolutionError; pub use self::LateBoundRegionConversionTime::*; @@ -338,6 +339,7 @@ pub struct InferCtxt<'tcx> { pub enum ValuePairs<'tcx> { Regions(ExpectedFound<ty::Region<'tcx>>), Terms(ExpectedFound<ty::Term<'tcx>>), + Aliases(ExpectedFound<ty::AliasTy<'tcx>>), TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>), PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>), Sigs(ExpectedFound<ty::FnSig<'tcx>>), @@ -729,7 +731,7 @@ impl<'tcx> InferCtxt<'tcx> { &'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, - define_opaque_types: bool, + define_opaque_types: DefineOpaqueTypes, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -864,7 +866,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok()) } pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool @@ -872,7 +874,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::No, a, b).is_ok()) } #[instrument(skip(self), level = "debug")] @@ -967,7 +969,8 @@ impl<'tcx> InferCtxt<'tcx> { let ty::SubtypePredicate { a_is_expected, a, b } = self.instantiate_binder_with_placeholders(predicate); - let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; + let ok = + self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)?; Ok(ok.unit()) })) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d5c824d4c41..ed4bc594d1a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,3 +1,5 @@ +use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use super::{DefineOpaqueTypes, InferResult}; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; @@ -16,18 +18,13 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; - use std::ops::ControlFlow; -pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>; - mod table; +pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>; pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; -use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::InferResult; - /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that /// appear in the return type). @@ -547,8 +544,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(prev) = prev { obligations = self .at(&cause, param_env) - .define_opaque_types(true) - .eq_exp(a_is_expected, prev, hidden_ty)? + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? .obligations; } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 3e8c2052de8..230cadb1184 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -1,5 +1,5 @@ use super::combine::{CombineFields, RelationDir}; -use super::{ObligationEmittingRelation, SubregionOrigin}; +use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; @@ -138,7 +138,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + && def_id.is_local() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 18d84a7023a..014810dba9c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -744,6 +744,7 @@ fn test_unstable_options_tracking_hash() { tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); + tracked!(flatten_format_args, true); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20ab0af5856..308c02929ca 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1390,7 +1390,7 @@ pub struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, - #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")] + #[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")] pub suggestion: Span, } @@ -1434,17 +1434,15 @@ pub struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] -pub enum UnusedDefSuggestion { - #[suggestion( - lint_suggestion, - style = "verbose", - code = "let _ = ", - applicability = "machine-applicable" - )] - Default { - #[primary_span] - span: Span, - }, +#[suggestion( + lint_suggestion, + style = "verbose", + code = "let _ = ", + applicability = "maybe-incorrect" +)] +pub struct UnusedDefSuggestion { + #[primary_span] + pub span: Span, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 62e8b4fe9e4..7c692fee333 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -56,6 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { return; } let arg_ty = cx.typeck_results().expr_ty(&args[0]); + let default_span = args[0].span; if let ty::FnDef(id, _) = arg_ty.kind() { let fn_ty = cx.tcx.fn_sig(id).skip_binder(); let ret_ty = fn_ty.output().skip_binder(); @@ -64,7 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, @@ -80,7 +84,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 2fab82d55cd..faca61fc29b 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); let type_lint_emitted_or_suppressed = match must_use_result { Some(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1); + emit_must_use_untranslated(cx, &path, "", "", 1, false); true } None => false, @@ -358,6 +358,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre_path, descr_post_path, 1, + false, ) }) .is_some() @@ -370,6 +371,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre: &str, descr_post: &str, plural_len: usize, + is_inner: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -377,20 +379,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { MustUsePath::Suppressed => {} MustUsePath::Boxed(path) => { let descr_pre = &format!("{}boxed ", descr_pre); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::Opaque(path) => { let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TraitObject(path) => { let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TupleElement(elems) => { for (index, path) in elems { let descr_post = &format!(" in tuple element {}", index); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated( + cx, path, descr_pre, descr_post, plural_len, true, + ); } } MustUsePath::Array(path, len) => { @@ -401,6 +405,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre, descr_post, plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), + true, ); } MustUsePath::Closure(span) => { @@ -418,19 +423,6 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { - let suggestion = if matches!( - cx.tcx.get_diagnostic_name(*def_id), - Some(sym::add) - | Some(sym::sub) - | Some(sym::mul) - | Some(sym::div) - | Some(sym::rem) - | Some(sym::neg), - ) { - Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() }) - } else { - None - }; cx.emit_spanned_lint( UNUSED_MUST_USE, *span, @@ -440,7 +432,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, - suggestion, + suggestion: (!is_inner) + .then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }), }, ); } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 46ec1a2dca1..91966e75b5f 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1026,12 +1026,13 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// #![feature(const_ptr_read)] + /// #![feature(const_mut_refs)] /// const FOO: () = unsafe { /// let x = &[0_u8; 4]; /// let y = x.as_ptr().cast::<u32>(); - /// y.read(); // the address of a `u8` array is unknown and thus we don't know if - /// // it is aligned enough for reading a `u32`. + /// let mut z = 123; + /// y.copy_to_nonoverlapping(&mut z, 1); // the address of a `u8` array is unknown + /// // and thus we don't know if it is aligned enough for copying a `u32`. /// }; /// ``` /// diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ca26e1497aa..0070e46ffdf 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1087,6 +1087,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; let container = self.root.tables.assoc_container.get(self, id).unwrap(); + let opt_rpitit_info = + self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self)); ty::AssocItem { name, @@ -1095,8 +1097,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { trait_item_def_id: self.get_trait_item_def_id(id), container, fn_has_self_parameter: has_self, - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): We need to encode this - opt_rpitit_info: None, + opt_rpitit_info, } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 6c5e8863010..a9843395336 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -226,7 +226,15 @@ provide! { tcx, def_id, other, cdata, lookup_default_body_stability => { table } lookup_deprecation_entry => { table } params_in_repr => { table } - unused_generic_params => { table } + // FIXME: Could be defaulted, but `LazyValue<UnusedGenericParams>` is not `FixedSizeEncoding`.. + unused_generic_params => { + cdata + .root + .tables + .unused_generic_params + .get(cdata, def_id.index) + .map_or_else(|| ty::UnusedGenericParams::new_all_used(), |lazy| lazy.decode((cdata, tcx))) + } opt_def_kind => { table_direct } impl_parent => { table } impl_polarity => { table_direct } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bbab8a62a2b..9649ce2c5a7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1350,19 +1350,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if trait_item.kind == ty::AssocKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } + if let Some(rpitit_info) = trait_item.opt_rpitit_info { + let rpitit_info = self.lazy(rpitit_info); + self.tables.opt_rpitit_info.set_some(def_id.index, rpitit_info); + } } fn encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); - self.tables.impl_defaultness.set_some(def_id.index, ast_item.defaultness); + let defaultness = self.tcx.impl_defaultness(def_id.expect_local()); + self.tables.impl_defaultness.set_some(def_id.index, defaultness); let impl_item = self.tcx.associated_item(def_id); self.tables.assoc_container.set_some(def_id.index, impl_item.container); match impl_item.kind { ty::AssocKind::Fn => { + let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set_some(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); @@ -1383,6 +1388,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } + if let Some(rpitit_info) = impl_item.opt_rpitit_info { + let rpitit_info = self.lazy(rpitit_info); + self.tables.opt_rpitit_info.set_some(def_id.index, rpitit_info); + } } fn encode_mir(&mut self) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 1d2541a6788..e71a1c98102 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -355,6 +355,7 @@ define_tables! { inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, associated_items_for_impl_trait_in_trait: Table<DefIndex, LazyArray<DefId>>, + opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>, - optional: attributes: Table<DefIndex, LazyArray<ast::Attribute>>, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 746cf488589..8a4c10cd71c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -316,7 +316,7 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. #[inline] pub fn find_by_def_id(self, id: LocalDefId) -> Option<Node<'hir>> { - self.find(self.local_def_id_to_hir_id(id)) + self.find(self.tcx.opt_local_def_id_to_hir_id(id)?) } /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. @@ -333,7 +333,7 @@ impl<'hir> Map<'hir> { } pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> { - id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id))) + id.as_local().and_then(|id| self.find(self.tcx.opt_local_def_id_to_hir_id(id)?)) } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 9312e27df37..a28ecfa9bdc 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1081,11 +1081,7 @@ pub enum Rvalue<'tcx> { /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. /// /// For addition, subtraction, and multiplication on integers the error condition is set when - /// the infinite precision result would be unequal to the actual result. - /// - /// For shift operations on integers the error condition is set when the value of right-hand - /// side is greater than or equal to the number of bits in the type of the left-hand side, or - /// when the value of right-hand side is negative. + /// the infinite precision result would not be equal to the actual result. /// /// Other combinations of types and operators are unsupported. CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 78ee8a6a8fd..6e961a775c1 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -63,7 +63,7 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { - true + self.def_id().is_local() } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -76,7 +76,7 @@ impl<'tcx> Key for ty::Instance<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { - true + self.def_id().is_local() } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 75f05c4af23..2cd79157441 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2215,7 +2215,7 @@ rustc_queries! { } /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being - /// equal to eachother. This might return `Ok` even if the types are unequal, but will never return `Err` if + /// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if /// the types might be equal. query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> { desc { "check whether two const param are definitely not equal to eachother"} diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index eecd78ab6c0..a7f38884ebc 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -237,7 +237,7 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to an unsigned integer of the given size. - /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the + /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. #[inline] pub fn try_to_uint(self, size: Size) -> Result<u128, Size> { @@ -297,7 +297,7 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to a signed integer of the given size. - /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the + /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. #[inline] pub fn try_to_int(self, size: Size) -> Result<i128, Size> { @@ -306,35 +306,35 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to i8. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 1 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 1 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i8(self) -> Result<i8, Size> { self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i16. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 2 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 2 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i16(self) -> Result<i16, Size> { self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i32. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 4 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 4 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i32(self) -> Result<i32, Size> { self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i64. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 8 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 8 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i64(self) -> Result<i64, Size> { self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i128. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 16 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 16 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i128(self) -> Result<i128, Size> { self.try_to_int(Size::from_bits(128)).map(|v| i128::try_from(v).unwrap()) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d5ba0785fa6..e4694809cd1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -71,6 +71,7 @@ use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; use std::any::Any; +use std::assert_matches::debug_assert_matches; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -2049,6 +2050,12 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { + debug_assert_matches!( + (kind, self.def_kind(alias_ty.def_id)), + (ty::Opaque, DefKind::OpaqueTy) + | (ty::Projection, DefKind::AssocTy) + | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + ); self.mk_ty_from_kind(Alias(kind, alias_ty)) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 254ffc33c96..42fb5d031bb 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -730,7 +730,11 @@ where */ }; - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() + // Projection eagerly bails out when the pointee references errors, + // fall back to structurally deducing metadata. + && !pointee.references_error() + { let metadata = tcx.normalize_erasing_regions( cx.param_env(), tcx.mk_projection(metadata_def_id, [pointee]), diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 8849e7eab33..7534d06ae91 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -63,6 +63,7 @@ trivially_parameterized_over_tcx! { ty::DeducedParamAttrs, ty::Generics, ty::ImplPolarity, + ty::ImplTraitInTraitData, ty::ReprOptions, ty::TraitDef, ty::UnusedGenericParams, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b0f6127baa5..dc585f438f4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -60,22 +60,13 @@ impl<'tcx> fmt::Display for Discr<'tcx> { } } -fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { - let (int, signed) = match *ty.kind() { - ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true), - ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), - _ => bug!("non integer discriminant"), - }; - (int.size(), signed) -} - impl<'tcx> Discr<'tcx> { /// Adds `1` to the value and wraps around if the maximum for the type is reached. pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self { self.checked_add(tcx, 1).0 } pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) { - let (size, signed) = int_size_and_signed(tcx, self.ty); + let (size, signed) = self.ty.int_size_and_signed(tcx); let (val, oflo) = if signed { let min = size.signed_int_min(); let max = size.signed_int_max(); @@ -929,12 +920,21 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { } impl<'tcx> Ty<'tcx> { + pub fn int_size_and_signed(self, tcx: TyCtxt<'tcx>) -> (Size, bool) { + let (int, signed) = match *self.kind() { + ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true), + ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), + _ => bug!("non integer discriminant"), + }; + (int.size(), signed) + } + /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { - let (size, signed) = int_size_and_signed(tcx, self); + let (size, signed) = self.int_size_and_signed(tcx); let val = if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() }; Some(val) @@ -955,7 +955,7 @@ impl<'tcx> Ty<'tcx> { pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { - let (size, signed) = int_size_and_signed(tcx, self); + let (size, signed) = self.int_size_and_signed(tcx); let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 }; Some(val) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index b8115f5aa18..9f48986b1ad 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -9,6 +9,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary}; use rustc_hir::lang_items::LangItem; use rustc_middle::middle::region; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::AssertKind; use rustc_middle::mir::Place; use rustc_middle::mir::*; @@ -519,30 +520,68 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> BlockAnd<Rvalue<'tcx>> { let source_info = self.source_info(span); let bool_ty = self.tcx.types.bool; - if self.check_overflow && op.is_checkable() && ty.is_integral() { - let result_tup = self.tcx.mk_tup(&[ty, bool_ty]); - let result_value = self.temp(result_tup, span); + let rvalue = match op { + BinOp::Add | BinOp::Sub | BinOp::Mul if self.check_overflow && ty.is_integral() => { + let result_tup = self.tcx.mk_tup(&[ty, bool_ty]); + let result_value = self.temp(result_tup, span); - self.cfg.push_assign( - block, - source_info, - result_value, - Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))), - ); - let val_fld = Field::new(0); - let of_fld = Field::new(1); + self.cfg.push_assign( + block, + source_info, + result_value, + Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))), + ); + let val_fld = Field::new(0); + let of_fld = Field::new(1); + + let tcx = self.tcx; + let val = tcx.mk_place_field(result_value, val_fld, ty); + let of = tcx.mk_place_field(result_value, of_fld, bool_ty); - let tcx = self.tcx; - let val = tcx.mk_place_field(result_value, val_fld, ty); - let of = tcx.mk_place_field(result_value, of_fld, bool_ty); + let err = AssertKind::Overflow(op, lhs, rhs); + block = self.assert(block, Operand::Move(of), false, err, span); - let err = AssertKind::Overflow(op, lhs, rhs); + Rvalue::Use(Operand::Move(val)) + } + BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => { + // Consider that the shift overflows if `rhs < 0` or `rhs >= bits`. + // This can be encoded as a single operation as `(rhs & -bits) != 0`. + let (size, _) = ty.int_size_and_signed(self.tcx); + let bits = size.bits(); + debug_assert!(bits.is_power_of_two()); + let mask = !((bits - 1) as u128); + + let rhs_ty = rhs.ty(&self.local_decls, self.tcx); + let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx); + let mask = Operand::const_from_scalar( + self.tcx, + rhs_ty, + Scalar::from_uint(rhs_size.truncate(mask), rhs_size), + span, + ); - block = self.assert(block, Operand::Move(of), false, err, span); + let outer_bits = self.temp(rhs_ty, span); + self.cfg.push_assign( + block, + source_info, + outer_bits, + Rvalue::BinaryOp(BinOp::BitAnd, Box::new((rhs.to_copy(), mask))), + ); - block.and(Rvalue::Use(Operand::Move(val))) - } else { - if ty.is_integral() && (op == BinOp::Div || op == BinOp::Rem) { + let overflows = self.temp(bool_ty, span); + let zero = self.zero_literal(span, rhs_ty); + self.cfg.push_assign( + block, + source_info, + overflows, + Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Move(outer_bits), zero))), + ); + + let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy()); + block = self.assert(block, Operand::Move(overflows), false, overflow_err, span); + Rvalue::BinaryOp(op, Box::new((lhs, rhs))) + } + BinOp::Div | BinOp::Rem if ty.is_integral() => { // Checking division and remainder is more complex, since we 1. always check // and 2. there are two possible failure cases, divide-by-zero and overflow. @@ -601,10 +640,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = self.assert(block, Operand::Move(of), false, overflow_err, span); } - } - block.and(Rvalue::BinaryOp(op, Box::new((lhs, rhs)))) - } + Rvalue::BinaryOp(op, Box::new((lhs, rhs))) + } + _ => Rvalue::BinaryOp(op, Box::new((lhs, rhs))), + }; + block.and(rvalue) } fn build_zero_repeat( diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index f596cc1808f..5d7382305ae 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -149,6 +149,35 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } } + sym::read_via_copy => { + let [arg] = args.as_slice() else { + span_bug!(terminator.source_info.span, "Wrong number of arguments"); + }; + let derefed_place = + if let Some(place) = arg.place() && let Some(local) = place.as_local() { + tcx.mk_place_deref(local.into()) + } else { + span_bug!(terminator.source_info.span, "Only passing a local is supported"); + }; + terminator.kind = match *target { + None => { + // No target means this read something uninhabited, + // so it must be unreachable, and we don't need to + // preserve the assignment either. + TerminatorKind::Unreachable + } + Some(target) => { + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::Use(Operand::Copy(derefed_place)), + ))), + }); + TerminatorKind::Goto { target } + } + } + } sym::discriminant_value => { if let (Some(target), Some(arg)) = (*target, args[0].place()) { let arg = tcx.mk_place_deref(arg); diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 1becfddb23b..1f37f03cff1 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -1,7 +1,9 @@ -//! Removes assignments to ZST places. +//! Removes operations on ZST places, and convert ZST operands to constants. use crate::MirPass; -use rustc_middle::mir::{Body, StatementKind}; +use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RemoveZsts; @@ -16,38 +18,24 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { if tcx.type_of(body.source.def_id()).subst_identity().is_generator() { return; } - let param_env = tcx.param_env(body.source.def_id()); - let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let local_decls = &body.local_decls; - for block in basic_blocks { - for statement in block.statements.iter_mut() { - if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) = - statement.kind - { - let place_ty = place.ty(local_decls, tcx).ty; - if !maybe_zst(place_ty) { - continue; - } - let Ok(layout) = tcx.layout_of(param_env.and(place_ty)) else { - continue; - }; - if !layout.is_zst() { - continue; - } - if tcx.consider_optimizing(|| { - format!( - "RemoveZsts - Place: {:?} SourceInfo: {:?}", - place, statement.source_info - ) - }) { - statement.make_nop(); - } - } - } + let mut replacer = Replacer { tcx, param_env, local_decls }; + for var_debug_info in &mut body.var_debug_info { + replacer.visit_var_debug_info(var_debug_info); + } + for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + replacer.visit_basic_block_data(bb, data); } } } +struct Replacer<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + local_decls: &'a LocalDecls<'tcx>, +} + /// A cheap, approximate check to avoid unnecessary `layout_of` calls. fn maybe_zst(ty: Ty<'_>) -> bool { match ty.kind() { @@ -63,3 +51,93 @@ fn maybe_zst(ty: Ty<'_>) -> bool { _ => false, } } + +impl<'tcx> Replacer<'_, 'tcx> { + fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool { + if !maybe_zst(ty) { + return false; + } + let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else { + return false; + }; + layout.is_zst() + } + + fn make_zst(&self, ty: Ty<'tcx>) -> Constant<'tcx> { + debug_assert!(self.known_to_be_zst(ty)); + Constant { + span: rustc_span::DUMMY_SP, + user_ty: None, + literal: ConstantKind::Val(ConstValue::ZeroSized, ty), + } + } +} + +impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) { + match var_debug_info.value { + VarDebugInfoContents::Const(_) => {} + VarDebugInfoContents::Place(place) => { + let place_ty = place.ty(self.local_decls, self.tcx).ty; + if self.known_to_be_zst(place_ty) { + var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(place_ty)) + } + } + VarDebugInfoContents::Composite { ty, fragments: _ } => { + if self.known_to_be_zst(ty) { + var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(ty)) + } + } + } + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { + if let Operand::Constant(_) = operand { + return; + } + let op_ty = operand.ty(self.local_decls, self.tcx); + if self.known_to_be_zst(op_ty) + && self.tcx.consider_optimizing(|| { + format!("RemoveZsts - Operand: {:?} Location: {:?}", operand, loc) + }) + { + *operand = Operand::Constant(Box::new(self.make_zst(op_ty))) + } + } + + fn visit_statement(&mut self, statement: &mut Statement<'tcx>, loc: Location) { + let place_for_ty = match statement.kind { + StatementKind::Assign(box (place, ref rvalue)) => { + rvalue.is_safe_to_remove().then_some(place) + } + StatementKind::Deinit(box place) + | StatementKind::SetDiscriminant { box place, variant_index: _ } + | StatementKind::AscribeUserType(box (place, _), _) + | StatementKind::Retag(_, box place) + | StatementKind::PlaceMention(box place) + | StatementKind::FakeRead(box (_, place)) => Some(place), + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + Some(local.into()) + } + StatementKind::Coverage(_) + | StatementKind::Intrinsic(_) + | StatementKind::Nop + | StatementKind::ConstEvalCounter => None, + }; + if let Some(place_for_ty) = place_for_ty + && let ty = place_for_ty.ty(self.local_decls, self.tcx).ty + && self.known_to_be_zst(ty) + && self.tcx.consider_optimizing(|| { + format!("RemoveZsts - Place: {:?} SourceInfo: {:?}", place_for_ty, statement.source_info) + }) + { + statement.make_nop(); + } else { + self.super_statement(statement, loc); + } + } +} diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index f529944acce..aff27e5664b 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1326,6 +1326,21 @@ fn create_mono_items_for_default_impls<'tcx>( return; } + // Unlike 'lazy' monomorphization that begins by collecting items transitively + // called by `main` or other global items, when eagerly monomorphizing impl + // items, we never actually check that the predicates of this impl are satisfied + // in a empty reveal-all param env (i.e. with no assumptions). + // + // Even though this impl has no substitutions, because we don't consider higher- + // ranked predicates such as `for<'a> &'a mut [u8]: Copy` to be trivially false, + // we must now check that the impl has no impossible-to-satisfy predicates. + if tcx.subst_and_check_impossible_predicates(( + item.owner_id.to_def_id(), + &InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()), + )) { + return; + } + let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else { return; }; diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index b7c3dbcc091..63263a642ac 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -36,6 +36,8 @@ fn unused_generic_params<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, ) -> UnusedGenericParams { + assert!(instance.def_id().is_local()); + if !tcx.sess.opts.unstable_opts.polymorphize { // If polymorphization disabled, then all parameters are used. return UnusedGenericParams::new_all_used(); @@ -100,13 +102,6 @@ fn should_polymorphize<'tcx>( return false; } - // Polymorphization results are stored in cross-crate metadata only when there are unused - // parameters, so assume that non-local items must have only used parameters (else this query - // would not be invoked, and the cross-crate metadata used instead). - if !def_id.is_local() { - return false; - } - // Foreign items have no bodies to analyze. if tcx.is_foreign_item(def_id) { return false; diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index faa9c493d88..44f991f8c15 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -22,3 +22,4 @@ rustc_span = { path = "../rustc_span" } rustc_lexer = { path = "../rustc_lexer" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_feature = { path = "../rustc_feature" } +rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 3fa78efc290..d063b51c8b8 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -720,26 +720,7 @@ passes_ignored_derived_impls = *[other] traits {$trait_list}, but these are } intentionally ignored during dead code analysis -passes_proc_macro_typeerror = mismatched {$kind} signature - .label = found {$found}, expected type `proc_macro::TokenStream` - .note = {$kind}s must have a signature of `{$expected_signature}` - -passes_proc_macro_diff_arg_count = mismatched {$kind} signature - .label = found unexpected {$count -> - [one] argument - *[other] arguments - } - .note = {$kind}s must have a signature of `{$expected_signature}` - -passes_proc_macro_missing_args = mismatched {$kind} signature - .label = {$kind} must have {$expected_input_count -> - [one] one argument - *[other] two arguments - } of type `proc_macro::TokenStream` - -passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"` - -passes_proc_macro_unsafe = proc macro functions may not be `unsafe` +passes_proc_macro_bad_sig = {$kind} has incorrect signature passes_skipping_const_checks = skipping const checks diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c8d371dd084..8bed7888142 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -19,9 +19,10 @@ use rustc_hir::{ use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES, @@ -30,6 +31,9 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; +use rustc_trait_selection::traits::ObligationCtxt; use std::cell::Cell; use std::collections::hash_map::Entry; @@ -2188,100 +2192,99 @@ impl CheckAttrVisitor<'_> { /// /// If this best effort goes wrong, it will just emit a worse error later (see #102923) fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) { - let expected_input_count = match kind { - ProcMacroKind::Attribute => 2, - ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1, - }; - - let expected_signature = match kind { - ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream", - ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream", - }; + if target != Target::Fn { + return; + } let tcx = self.tcx; - if target == Target::Fn { - let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return}; - let tokenstream = tcx.type_of(tokenstream).subst_identity(); - - let id = hir_id.expect_owner(); - let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap(); - - let sig = - tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity()); - let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig); - - // We don't currently require that the function signature is equal to - // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to - // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments. - // - // Properly checking this means pulling in additional `rustc` crates, so we don't. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; - - if sig.abi != Abi::Rust { - tcx.sess.emit_err(errors::ProcMacroInvalidAbi { - span: hir_sig.span, - abi: sig.abi.name(), - }); - self.abort.set(true); - } + let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else { return; }; + let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else { return; }; - if sig.unsafety == Unsafety::Unsafe { - tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span }); - self.abort.set(true); - } + let def_id = hir_id.expect_owner().def_id; + let param_env = ty::ParamEnv::empty(); - let output = sig.output(); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); - // Typecheck the output - if !drcx.types_may_unify(output, tokenstream) { - tcx.sess.emit_err(errors::ProcMacroTypeError { - span: hir_sig.decl.output.span(), - found: output, - kind, - expected_signature, - }); - self.abort.set(true); - } + let span = tcx.def_span(def_id); + let fresh_substs = infcx.fresh_substs_for_item(span, def_id.to_def_id()); + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).subst(tcx, fresh_substs), + ); - if sig.inputs().len() < expected_input_count { - tcx.sess.emit_err(errors::ProcMacroMissingArguments { - expected_input_count, - span: hir_sig.span, - kind, - expected_signature, - }); - self.abort.set(true); - } + let mut cause = ObligationCause::misc(span, def_id); + let sig = ocx.normalize(&cause, param_env, sig); - // Check that the inputs are correct, if there are enough. - if sig.inputs().len() >= expected_input_count { - for (arg, input) in - sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count) - { - if !drcx.types_may_unify(*arg, tokenstream) { - tcx.sess.emit_err(errors::ProcMacroTypeError { - span: input.span, - found: *arg, - kind, - expected_signature, - }); - self.abort.set(true); + // proc macro is not WF. + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return; + } + + let expected_sig = tcx.mk_fn_sig( + std::iter::repeat(token_stream).take(match kind { + ProcMacroKind::Attribute => 2, + ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1, + }), + token_stream, + false, + Unsafety::Normal, + Abi::Rust, + ); + + if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) { + let mut diag = tcx.sess.create_err(errors::ProcMacroBadSig { span, kind }); + + let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id); + if let Some(hir_sig) = hir_sig { + match terr { + TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { + if let Some(ty) = hir_sig.decl.inputs.get(idx) { + diag.set_span(ty.span); + cause.span = ty.span; + } else if idx == hir_sig.decl.inputs.len() { + let span = hir_sig.decl.output.span(); + diag.set_span(span); + cause.span = span; + } + } + TypeError::ArgCount => { + if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { + diag.set_span(ty.span); + cause.span = ty.span; + } } + TypeError::UnsafetyMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + TypeError::AbiMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + TypeError::VariadicMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + _ => {} } } - // Check that there are not too many arguments - let body_id = tcx.hir().body_owned_by(id.def_id); - let excess = tcx.hir().body(body_id).params.get(expected_input_count..); - if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess { - tcx.sess.emit_err(errors::ProcMacroDiffArguments { - span: begin.span.to(end.span), - count: excess.len(), - kind, - expected_signature, - }); - self.abort.set(true); - } + infcx.err_ctxt().note_type_err( + &mut diag, + &cause, + None, + Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })), + terr, + false, + false, + ); + diag.emit(); + self.abort.set(true); + } + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(&errors); + self.abort.set(true); } } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9f1c0b5a0b7..1b0cd5d91ab 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1546,52 +1546,11 @@ pub struct ChangeFieldsToBeOfUnitType { } #[derive(Diagnostic)] -#[diag(passes_proc_macro_typeerror)] -#[note] -pub(crate) struct ProcMacroTypeError<'tcx> { - #[primary_span] - #[label] - pub span: Span, - pub found: Ty<'tcx>, - pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_diff_arg_count)] -pub(crate) struct ProcMacroDiffArguments { - #[primary_span] - #[label] - pub span: Span, - pub count: usize, - pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_missing_args)] -pub(crate) struct ProcMacroMissingArguments { +#[diag(passes_proc_macro_bad_sig)] +pub(crate) struct ProcMacroBadSig { #[primary_span] - #[label] pub span: Span, - pub expected_input_count: usize, pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_invalid_abi)] -pub(crate) struct ProcMacroInvalidAbi { - #[primary_span] - pub span: Span, - pub abi: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_unsafe)] -pub(crate) struct ProcMacroUnsafe { - #[primary_span] - pub span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 805c2ff280d..df7681dc426 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1289,25 +1289,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => { let span = find_span(&source, err); err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here")); - let (tail, descr, applicability) = match source { - PathSource::Pat | PathSource::TupleStruct(..) => { - ("", "pattern", Applicability::MachineApplicable) - } - _ => (": val", "literal", Applicability::HasPlaceholders), - }; + let (tail, descr, applicability, old_fields) = match source { + PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None), + PathSource::TupleStruct(_, args) => ( + "", + "pattern", + Applicability::MachineApplicable, + Some( + args.iter() + .map(|a| self.r.tcx.sess.source_map().span_to_snippet(*a).ok()) + .collect::<Vec<Option<String>>>(), + ), + ), + _ => (": val", "literal", Applicability::HasPlaceholders, None), + }; let field_ids = self.r.field_def_ids(def_id); let (fields, applicability) = match field_ids { - Some(field_ids) => ( - field_ids - .iter() - .map(|&field_id| { - format!("{}{tail}", self.r.tcx.item_name(field_id)) - }) - .collect::<Vec<String>>() - .join(", "), - applicability, - ), + Some(field_ids) => { + let fields = field_ids.iter().map(|&id| self.r.tcx.item_name(id)); + + let fields = if let Some(old_fields) = old_fields { + fields + .enumerate() + .map(|(idx, new)| (new, old_fields.get(idx))) + .map(|(new, old)| { + let new = new.to_ident_string(); + if let Some(Some(old)) = old && new != *old { format!("{}: {}", new, old) } else { new } + }) + .collect::<Vec<String>>() + } else { + fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>() + }; + + (fields.join(", "), applicability) + } None => ("/* fields */".to_string(), Applicability::HasPlaceholders), }; let pad = match field_ids { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b466a3fcdee..0548379dc2f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1422,6 +1422,9 @@ options! { fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), + flatten_format_args: bool = (false, parse_bool, [TRACKED], + "flatten nested format_args!() and literals into a simplified format_args!() call \ + (default: no)"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable (default: no)"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d8b5b25aaee..abe5af8f9e0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -984,6 +984,7 @@ symbols! { never_type_fallback, new, new_binary, + new_const, new_debug, new_display, new_lower_exp, @@ -1153,6 +1154,7 @@ symbols! { read_enum_variant_arg, read_struct, read_struct_field, + read_via_copy, readonly, realloc, reason, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0d86a3032a6..f3304e91429 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1115,6 +1115,7 @@ supported_targets! { // FIXME(#106649): Remove aarch64-fuchsia in favor of aarch64-unknown-fuchsia ("aarch64-fuchsia", aarch64_fuchsia), ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia), + ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia), // FIXME(#106649): Remove x86_64-fuchsia in favor of x86_64-unknown-fuchsia ("x86_64-fuchsia", x86_64_fuchsia), ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs new file mode 100644 index 00000000000..ab7c08958fa --- /dev/null +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs @@ -0,0 +1,19 @@ +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64gc-unknown-fuchsia".into(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".into(), + features: "+m,+a,+f,+d,+c".into(), + llvm_abiname: "lp64d".into(), + max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::SHADOWCALLSTACK, + ..super::fuchsia_base::opts() + }, + } +} diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index ca438a103cf..856f1eec443 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; @@ -144,7 +144,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> { self.infcx .at(&ObligationCause::dummy(), param_env) - .eq(lhs, rhs) + .eq(DefineOpaqueTypes::No, lhs, rhs) .map(|InferOk { value: (), obligations }| { obligations.into_iter().map(|o| o.into()).collect() }) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 55d361b1204..a873060687d 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,7 +19,7 @@ use std::mem; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -268,7 +268,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let InferOk { value: (), obligations } = self .infcx .at(&ObligationCause::dummy(), goal.param_env) - .sub(goal.predicate.a, goal.predicate.b)?; + .sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?; self.evaluate_all_and_make_canonical_response( obligations.into_iter().map(|pred| pred.into()).collect(), ) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1fb8659bb27..1870d3a2daf 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -7,6 +7,7 @@ use crate::errors::UnableToConstructConstantValue; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitableExt; @@ -814,7 +815,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::No,c1, c2) { Ok(_) => (), Err(_) => return false, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 96a4b76af55..f4cfe4ec0b0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -17,7 +17,7 @@ use crate::traits::{ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; @@ -181,7 +181,7 @@ fn overlap_within_probe<'cx, 'tcx>( let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id); let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id); - let obligations = equate_impl_headers(selcx, &impl1_header, &impl2_header)?; + let obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); if overlap_mode.use_implicit_negative() { @@ -207,20 +207,25 @@ fn overlap_within_probe<'cx, 'tcx>( Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } -fn equate_impl_headers<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - impl1_header: &ty::ImplHeader<'tcx>, - impl2_header: &ty::ImplHeader<'tcx>, +#[instrument(level = "debug", skip(infcx), ret)] +fn equate_impl_headers<'tcx>( + infcx: &InferCtxt<'tcx>, + impl1: &ty::ImplHeader<'tcx>, + impl2: &ty::ImplHeader<'tcx>, ) -> Option<PredicateObligations<'tcx>> { - // Do `a` and `b` unify? If not, no overlap. - debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header); - selcx - .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .define_opaque_types(true) - .eq_impl_headers(impl1_header, impl2_header) - .map(|infer_ok| infer_ok.obligations) - .ok() + let result = match (impl1.trait_ref, impl2.trait_ref) { + (Some(impl1_ref), Some(impl2_ref)) => infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .eq(DefineOpaqueTypes::Yes, impl1_ref, impl2_ref), + (None, None) => infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq( + DefineOpaqueTypes::Yes, + impl1.self_ty, + impl2.self_ty, + ), + _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), + }; + + result.map(|infer_ok| infer_ok.obligations).ok() } /// Given impl1 and impl2 check if both impls can be satisfied by a common type (including @@ -325,7 +330,7 @@ fn equate<'tcx>( ) -> bool { // do the impls unify? If not, not disjoint. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), impl_env).eq(subject1, subject2) + infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2) else { debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2); return true; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 62d5e50dbc5..8acc31cd410 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; -use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::query::Fallible; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, @@ -128,8 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .eq_exp(a_is_expected, a, b) + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, a, b) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -142,8 +141,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .eq(expected, actual) + .eq(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -157,8 +155,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .sub(expected, actual) + .sub(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -172,8 +169,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .sup(expected, actual) + .sup(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index b3bf9ad599a..277926688e2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -144,6 +144,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, ) -> OnUnimplementedNote { + if self.tcx.opt_rpitit_info(obligation.cause.body_id.to_def_id()).is_some() { + return OnUnimplementedNote::default(); + } + let (def_id, substs) = self .impl_similar_to(trait_ref, obligation) .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs)); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 944436ab82f..1aaadae12dd 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -2,6 +2,7 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; @@ -515,7 +516,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) .trace(c1, c2) - .eq(a.substs, b.substs) + .eq(DefineOpaqueTypes::No, a.substs, b.substs) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), @@ -524,8 +525,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } (_, Unevaluated(_)) | (Unevaluated(_), _) => (), (_, _) => { - if let Ok(new_obligations) = - infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + if let Ok(new_obligations) = infcx + .at(&obligation.cause, obligation.param_env) + .eq(DefineOpaqueTypes::No, c1, c2) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), @@ -565,12 +567,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) - { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + c1, + c2, + ) { Ok(inf_ok) => { ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) } @@ -610,12 +611,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { bug!("AliasEq is only used for new solver") } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(ct.ty(), ty) - { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + ct.ty(), + ty, + ) { Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 4eacb5211f7..a5def4151bf 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -13,7 +13,6 @@ use super::{elaborate_predicates, elaborate_trait_ref}; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, Obligation, ObligationCause}; -use hir::def::DefKind; use rustc_errors::{DelayDm, FatalError, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -157,6 +156,7 @@ fn object_safety_violations_for_trait( .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) + .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none()) .map(|item| { let ident = item.ident(tcx); ObjectSafetyViolation::GAT(ident.name, ident.span) @@ -854,7 +854,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>( } } ty::Alias(ty::Projection, ref data) - if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder => + if self.tcx.is_impl_trait_in_trait(data.def_id) => { // We'll deny these later in their own pass ControlFlow::Continue(()) @@ -921,7 +921,7 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>( ty.skip_binder().walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() && let ty::Alias(ty::Projection, proj) = ty.kind() - && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder + && tcx.is_impl_trait_in_trait(proj.def_id) { Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id))) } else { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 01075d7c55a..0f0cccea130 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,6 +28,7 @@ use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ImplSourceBuiltinData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -285,12 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>( ); obligations.extend(new); - match infcx - .at(&obligation.cause, obligation.param_env) - // This is needed to support nested opaque types like `impl Fn() -> impl Trait` - .define_opaque_types(true) - .eq(normalized, actual) - { + // Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait` + match infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::Yes, + normalized, + actual, + ) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); ProjectAndUnifyResult::Holds(obligations) @@ -467,6 +468,11 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx return ty; } + let (kind, data) = match *ty.kind() { + ty::Alias(kind, alias_ty) => (kind, alias_ty), + _ => return ty.super_fold_with(self), + }; + // We try to be a little clever here as a performance optimization in // cases where there are nested projections under binders. // For example: @@ -490,13 +496,11 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx // replace bound vars if the current type is a `Projection` and we need // to make sure we don't forget to fold the substs regardless. - match *ty.kind() { + match kind { // This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) - if !substs.has_escaping_bound_vars() => - { + ty::Opaque if !data.substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.super_fold_with(self), @@ -512,8 +516,8 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx ); } - let substs = substs.fold_with(self); - let generic_ty = self.interner().type_of(def_id); + let substs = data.substs.fold_with(self); + let generic_ty = self.interner().type_of(data.def_id); let concrete_ty = generic_ty.subst(self.interner(), substs); self.depth += 1; let folded_ty = self.fold_ty(concrete_ty); @@ -522,8 +526,9 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx } } } + ty::Opaque => ty.super_fold_with(self), - ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => { + ty::Projection if !data.has_escaping_bound_vars() => { // This branch is *mostly* just an optimization: when we don't // have escaping bound vars, we don't need to replace them with // placeholders (see branch below). *Also*, we know that we can @@ -562,7 +567,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx normalized_ty.ty().unwrap() } - ty::Alias(ty::Projection, data) => { + ty::Projection => { // If there are escaping bound vars, we temporarily replace the // bound vars with placeholders. Note though, that in the case // that we still can't project for whatever reason (e.g. self @@ -611,8 +616,6 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx ); normalized_ty } - - _ => ty.super_fold_with(self), } } @@ -2064,7 +2067,11 @@ fn confirm_param_env_candidate<'cx, 'tcx>( debug!(?cache_projection, ?obligation_projection); - match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { + match infcx.at(cause, param_env).eq( + DefineOpaqueTypes::No, + cache_projection, + obligation_projection, + ) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b0cec3ce7a3..a986a9b6a71 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> return Ok(*ty); } + let (kind, data) = match *ty.kind() { + ty::Alias(kind, data) => (kind, data), + _ => { + let res = ty.try_super_fold_with(self)?; + self.cache.insert(ty, res); + return Ok(res); + } + }; + // See note in `rustc_trait_selection::traits::project` about why we // wait to fold the substs. // Wrap this in a closure so we don't accidentally return from the outer function - let res = match *ty.kind() { + let res = match kind { // This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) - if !substs.has_escaping_bound_vars() => - { + ty::Opaque if !data.substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.try_super_fold_with(self)?, Reveal::All => { - let substs = substs.try_fold_with(self)?; + let substs = data.substs.try_fold_with(self)?; let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { // A closure or generator may have itself as in its upvars. @@ -228,7 +235,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> return ty.try_super_fold_with(self); } - let generic_ty = self.interner().type_of(def_id); + let generic_ty = self.interner().type_of(data.def_id); let concrete_ty = generic_ty.subst(self.interner(), substs); self.anon_depth += 1; if concrete_ty == ty { @@ -248,62 +255,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> } } - ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => { - // This branch is just an optimization: when we don't have escaping bound vars, - // we don't need to replace them with placeholders (see branch below). - - let tcx = self.infcx.tcx; - let data = data.try_fold_with(self)?; - - let mut orig_values = OriginalQueryValues::default(); - // HACK(matthewjasper) `'static` is special-cased in selection, - // so we cannot canonicalize it. - let c_data = self - .infcx - .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); - debug!("QueryNormalizer: c_data = {:#?}", c_data); - debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - let result = tcx.normalize_projection_ty(c_data)?; - // We don't expect ambiguity. - if result.is_ambiguous() { - // Rustdoc normalizes possibly not well-formed types, so only - // treat this as a bug if we're not in rustdoc. - if !tcx.sess.opts.actually_rustdoc { - tcx.sess.delay_span_bug( - DUMMY_SP, - format!("unexpected ambiguity: {:?} {:?}", c_data, result), - ); - } - return Err(NoSolution); - } - let InferOk { value: result, obligations } = - self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - )?; - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - - let res = result.normalized_ty; - // `tcx.normalize_projection_ty` may normalize to a type that still has - // unevaluated consts, so keep normalizing here if that's the case. - if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { - res.try_super_fold_with(self)? - } else { - res - } - } + ty::Opaque => ty.try_super_fold_with(self)?, - ty::Alias(ty::Projection, data) => { + ty::Projection => { // See note in `rustc_trait_selection::traits::project` let tcx = self.infcx.tcx; let infcx = self.infcx; - let (data, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + // Just an optimization: When we don't have escaping bound vars, + // we don't need to replace them with placeholders. + let (data, maps) = if data.has_escaping_bound_vars() { + let (data, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + (data, Some((mapped_regions, mapped_types, mapped_consts))) + } else { + (data, None) + }; let data = data.try_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); @@ -337,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - let res = PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result.normalized_ty, - ); + let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps { + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + ) + } else { + result.normalized_ty + }; // `tcx.normalize_projection_ty` may normalize to a type that still has // unevaluated consts, so keep normalizing here if that's the case. if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { @@ -353,8 +324,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> res } } - - _ => ty.try_super_fold_with(self)?, }; self.cache.insert(ty, res); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ee41d840bae..3d5dd18f4c1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,8 +8,8 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::{ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -177,7 +177,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate, candidate) + .sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -462,7 +462,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation_trait_ref, upcast_trait_ref) + .sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -827,11 +827,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); + // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs self.infcx .at(&obligation.cause, obligation.param_env) - // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs - .define_opaque_types(true) - .sup(obligation_trait_ref, expected_trait_ref) + .sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref) .map(|InferOk { mut obligations, .. }| { obligations.extend(nested); obligations @@ -896,7 +895,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .sup(DefineOpaqueTypes::No, target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -995,7 +994,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .sup(DefineOpaqueTypes::No, target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1066,7 +1065,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(b, a) + .eq(DefineOpaqueTypes::No, b, a) .map_err(|_| Unimplemented)?; nested.extend(obligations); } @@ -1114,7 +1113,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_struct) + .eq(DefineOpaqueTypes::No, target, new_struct) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1144,7 +1143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_tuple) + .eq(DefineOpaqueTypes::No, target, new_tuple) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 38cdaddc1e7..bc1c72da1e1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,6 +38,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngineExt; @@ -912,7 +913,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .at(&obligation.cause, obligation.param_env) .trace(c1, c2) - .eq(a.substs, b.substs) + .eq(DefineOpaqueTypes::No, a.substs, b.substs) { let mut obligations = new_obligations.obligations; self.add_depth( @@ -930,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Ok(new_obligations) = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) + .eq(DefineOpaqueTypes::No, c1, c2) { let mut obligations = new_obligations.obligations; self.add_depth( @@ -964,8 +965,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) - { + match self.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + c1, + c2, + ) { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, inf_ok.into_obligations(), @@ -993,7 +997,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) { + match self.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + ct.ty(), + ty, + ) { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, inf_ok.into_obligations(), @@ -1751,7 +1759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); self.infcx .at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) + .sup(DefineOpaqueTypes::No, ty::Binder::dummy(placeholder_trait_ref), trait_bound) .map(|InferOk { obligations: _, value: () }| { // This method is called within a probe, so we can't have // inference variables and placeholders escape. @@ -1813,7 +1821,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let is_match = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate, infer_projection) + .sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection) .map_or(false, |InferOk { obligations, value: () }| { self.evaluate_predicates_recursively( TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), @@ -2534,7 +2542,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&cause, obligation.param_env) - .eq(placeholder_obligation_trait_ref, impl_trait_ref) + .eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| { debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx())) })?; @@ -2584,7 +2592,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ) -> Result<Vec<PredicateObligation<'tcx>>, ()> { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) + .sup(DefineOpaqueTypes::No, obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| ()) } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index fcfb60b2603..8e229dd8d6b 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,6 +10,7 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; +use rustc_infer::infer::DefineOpaqueTypes; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; @@ -193,7 +194,7 @@ fn fulfill_implication<'tcx>( // do the impls unify? If not, no specialization. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait) + infcx.at(&ObligationCause::dummy(), param_env, ).eq(DefineOpaqueTypes::No,source_trait, target_trait) else { debug!( "fulfill_implication: {:?} does not unify with {:?}", diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bcf63d5a6f6..ab4c36975a0 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,15 +1,14 @@ -use rustc_errors::Diagnostic; -use rustc_span::Span; -use smallvec::SmallVec; - +use super::NormalizeExt; +use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Diagnostic; use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferOk; use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, SubstsRef}; +use rustc_span::Span; +use smallvec::SmallVec; -use super::NormalizeExt; -use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; -use rustc_infer::infer::InferOk; pub use rustc_infer::traits::{self, util::*}; /////////////////////////////////////////////////////////////////////////// @@ -201,6 +200,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( ) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) { let subject = selcx.tcx().bound_impl_subject(impl_def_id); let subject = subject.subst(selcx.tcx(), impl_substs); + let InferOk { value: subject, obligations: normalization_obligations1 } = selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject); diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 867974749d5..a2816124538 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -328,6 +328,9 @@ fn impl_associated_item_for_impl_trait_in_trait( // `opt_local_def_id_to_hir_id` with `None`. impl_assoc_ty.opt_local_def_id_to_hir_id(None); + // Copy span of the opaque. + impl_assoc_ty.def_ident_span(Some(span)); + impl_assoc_ty.associated_item(ty::AssocItem { name: kw::Empty, kind: ty::AssocKind::Type, @@ -342,6 +345,9 @@ fn impl_associated_item_for_impl_trait_in_trait( // extra predicates to assume. impl_assoc_ty.param_env(tcx.param_env(impl_fn_def_id)); + // Copy visility of the containing function. + impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id)); + // Copy impl_defaultness of the containing function. impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id)); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index e3132fcc4c4..1788f544a7f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -156,7 +156,11 @@ fn layout_of_uncached<'tcx>( let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() + // Projection eagerly bails out when the pointee references errors, + // fall back to structurally deducing metadata. + && !pointee.references_error() + { let metadata_ty = tcx.normalize_erasing_regions( param_env, tcx.mk_projection(metadata_def_id, [pointee]), diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index c8ed1f365f1..d41bf603983 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -119,12 +119,9 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // When computing the param_env of an RPITIT, copy param_env of the containing function. The // synthesized associated type doesn't have extra predicates to assume. - let def_id = - if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) { - fn_def_id - } else { - def_id - }; + if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) { + return tcx.param_env(fn_def_id); + } // Compute the bounds on Self and the type parameters. let ty::InstantiatedPredicates { mut predicates, .. } = |
