diff options
| author | bors <bors@rust-lang.org> | 2024-07-16 21:46:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-07-16 21:46:24 +0000 |
| commit | 7d356ebde329df5f38186efe3e7c5e8dabac7cb7 (patch) | |
| tree | 314d1e77a6a89745c12133d1376ee5a3b9ee5f3e | |
| parent | 032be6f7bbe091c7dfa29f115e94b9cc9bae1758 (diff) | |
| parent | 7d534dd4eb176dc60f0ca4615ce5fb9c32313884 (diff) | |
| download | rust-7d356ebde329df5f38186efe3e7c5e8dabac7cb7.tar.gz rust-7d356ebde329df5f38186efe3e7c5e8dabac7cb7.zip | |
Auto merge of #127831 - tgross35:rollup-c0j9n7b, r=tgross35
Rollup of 7 pull requests Successful merges: - #124033 (Sync ar_archive_writer to LLVM 18.1.3) - #126699 (Delegation: support coercion for target expression) - #126762 (Deny keyword lifetimes pre-expansion) - #126967 (Promote the `wasm32-wasip2` target to Tier 2) - #127390 (Migrate `raw-dylib-inline-cross-dylib` and `raw-dylib-custom-dlltool` `run-make` tests to rmake) - #127501 (Invert infer `error_reporting` mod struture) - #127816 (Update method name to reflect changes to its internals) r? `@ghost` `@rustbot` modify labels: rollup
87 files changed, 1429 insertions, 338 deletions
diff --git a/Cargo.lock b/Cargo.lock index 68478d55e23..ff755e5bec6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,11 +236,11 @@ checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" [[package]] name = "ar_archive_writer" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +checksum = "f8412a2d690663356cba5a2532f3ed55d1e8090743bc6695b88403b27df67733" dependencies = [ - "object 0.32.2", + "object 0.35.0", ] [[package]] @@ -1682,6 +1682,7 @@ dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", + "serde", ] [[package]] @@ -1892,6 +1893,12 @@ dependencies = [ ] [[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2121,6 +2128,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] +name = "lexopt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" + +[[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2634,7 +2647,7 @@ dependencies = [ "indexmap", "memchr", "ruzstd 0.5.0", - "wasmparser", + "wasmparser 0.118.2", ] [[package]] @@ -2650,6 +2663,15 @@ dependencies = [ [[package]] name = "object" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" @@ -3436,7 +3458,7 @@ dependencies = [ "object 0.34.0", "regex", "similar", - "wasmparser", + "wasmparser 0.118.2", ] [[package]] @@ -3823,7 +3845,7 @@ dependencies = [ "thin-vec", "thorin-dwp", "tracing", - "wasm-encoder", + "wasm-encoder 0.200.0", "windows", ] @@ -5268,6 +5290,15 @@ dependencies = [ ] [[package]] +name = "spdx" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +dependencies = [ + "smallvec", +] + +[[package]] name = "spdx-expression" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6316,6 +6347,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] +name = "wasm-component-ld" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "314d932d5e84c9678751b85498b1482b2f32f185744e449d3ce0b1d400376dad" +dependencies = [ + "anyhow", + "clap", + "lexopt", + "tempfile", + "wasmparser 0.210.0", + "wat", + "wit-component", +] + +[[package]] +name = "wasm-component-ld-wrapper" +version = "0.1.0" +dependencies = [ + "wasm-component-ld", +] + +[[package]] name = "wasm-encoder" version = "0.200.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6325,6 +6378,40 @@ dependencies = [ ] [[package]] +name = "wasm-encoder" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e3764d9d6edabd8c9e16195e177be0d20f6ab942ad18af52860f12f82bc59a" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.211.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e7d931a1120ef357f32b74547646b6fa68ea25e377772b72874b131a9ed70d4" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "012729d1294907fcb0866f08460ab95426a6d0b176a599619b84cac7653452b4" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.210.0", + "wasmparser 0.210.0", +] + +[[package]] name = "wasmparser" version = "0.118.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6335,6 +6422,42 @@ dependencies = [ ] [[package]] +name = "wasmparser" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7bbcd21e7581619d9f6ca00f8c4f08f1cacfe58bf63f83af57cd0476f1026f5" +dependencies = [ + "ahash", + "bitflags 2.5.0", + "hashbrown", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wast" +version = "211.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25506dd82d00da6b14a87436b3d52b1d264083fa79cdb72a0d1b04a8595ccaa" +dependencies = [ + "bumpalo", + "leb128", + "memchr", + "unicode-width", + "wasm-encoder 0.211.1", +] + +[[package]] +name = "wat" +version = "1.211.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb716ca6c86eecac2d82541ffc39860118fc0af9309c4f2670637bea2e1bdd7d" +dependencies = [ + "wast", +] + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6562,6 +6685,43 @@ dependencies = [ ] [[package]] +name = "wit-component" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a450bdb5d032acf1fa0865451fa0c6f50e62f2d31eaa8dba967c2e2d068694a4" +dependencies = [ + "anyhow", + "bitflags 2.5.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.210.0", + "wasm-metadata", + "wasmparser 0.210.0", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a965cbd439af19a4b44a54a97ab8957d86f02d01320efc9e31c1d3605c6710" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.210.0", +] + +[[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 93c520b0d68..ce87a8c20b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ members = [ "src/tools/opt-dist", "src/tools/coverage-dump", "src/tools/rustc-perf-wrapper", + "src/tools/wasm-component-ld", ] exclude = [ @@ -104,6 +105,9 @@ rustc-demangle.debug = 0 [profile.release.package.lld-wrapper] debug = 0 strip = true +[profile.release.package.wasm-component-ld-wrapper] +debug = 0 +strip = true [patch.crates-io] # See comments in `library/rustc-std-workspace-core/README.md` for what's going on diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 678cac210f4..6df2c15ce60 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -38,7 +38,7 @@ use crate::{ImplTraitPosition, ResolverAstLoweringExt}; -use super::{ImplTraitContext, LoweringContext, ParamMode}; +use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; use ast::visit::Visitor; use hir::def::{DefKind, PartialRes, Res}; @@ -259,8 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self_param_id: pat_node_id, }; self_resolver.visit_block(block); - let block = this.lower_block(block, false); - this.mk_expr(hir::ExprKind::Block(block, None), block.span) + this.lower_target_expr(&block) } else { let pat_hir_id = this.lower_node_id(pat_node_id); this.generate_arg(pat_hir_id, span) @@ -273,26 +272,81 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } - // Generates fully qualified call for the resulting body. + // FIXME(fn_delegation): Alternatives for target expression lowering: + // https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600. + fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> { + if block.stmts.len() == 1 + && let StmtKind::Expr(expr) = &block.stmts[0].kind + { + return self.lower_expr_mut(expr); + } + + let block = self.lower_block(block, false); + self.mk_expr(hir::ExprKind::Block(block, None), block.span) + } + + // Generates expression for the resulting body. If possible, `MethodCall` is used + // to allow autoref/autoderef for target expression. For example in: + // + // trait Trait : Sized { + // fn by_value(self) -> i32 { 1 } + // fn by_mut_ref(&mut self) -> i32 { 2 } + // fn by_ref(&self) -> i32 { 3 } + // } + // + // struct NewType(SomeType); + // impl Trait for NewType { + // reuse Trait::* { self.0 } + // } + // + // `self.0` will automatically coerce. fn finalize_body_lowering( &mut self, delegation: &Delegation, args: Vec<hir::Expr<'hir>>, span: Span, ) -> hir::Expr<'hir> { - let path = self.lower_qpath( - delegation.id, - &delegation.qself, - &delegation.path, - ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, - ); - let args = self.arena.alloc_from_iter(args); - let path_expr = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span)); - let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(path_expr, args), span)); + let has_generic_args = + delegation.path.segments.iter().rev().skip(1).any(|segment| segment.args.is_some()); + + let call = if self + .get_resolution_id(delegation.id, span) + .and_then(|def_id| Ok(self.has_self(def_id, span))) + .unwrap_or_default() + && delegation.qself.is_none() + && !has_generic_args + { + let ast_segment = delegation.path.segments.last().unwrap(); + let segment = self.lower_path_segment( + delegation.path.span, + ast_segment, + ParamMode::Optional, + ParenthesizedGenericArgs::Err, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + let segment = self.arena.alloc(segment); + + self.arena.alloc(hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::MethodCall(segment, &args[0], &args[1..], span), + span, + }) + } else { + let path = self.lower_qpath( + delegation.id, + &delegation.qself, + &delegation.path, + ParamMode::Optional, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + + let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span)); + self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span)) + }; let block = self.arena.alloc(hir::Block { stmts: &[], expr: Some(call), diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 7da726ef408..02bdff96aa6 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -159,9 +159,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} .type = inherent impl for this type .only_trait = only trait implementations may be annotated with {$annotation} -ast_passes_invalid_label = - invalid label name `{$name}` - ast_passes_invalid_unnamed_field = unnamed fields are not allowed outside of structs or unions .label = unnamed field declared here @@ -176,9 +173,6 @@ ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot ast_passes_item_underscore = `{$kind}` items in this context need a name .label = `_` is not a valid name for this `{$kind}` item -ast_passes_keyword_lifetime = - lifetimes cannot use keyword names - ast_passes_match_arm_with_no_body = `match` arm with no body .suggestion = add a body after the pattern diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index e6cc2e4069b..83249dea82a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -269,19 +269,6 @@ impl<'a> AstValidator<'a> { self.session.dcx() } - fn check_lifetime(&self, ident: Ident) { - let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty]; - if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() { - self.dcx().emit_err(errors::KeywordLifetime { span: ident.span }); - } - } - - fn check_label(&self, ident: Ident) { - if ident.without_first_quote().is_reserved() { - self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name }); - } - } - fn visibility_not_permitted(&self, vis: &Visibility, note: errors::VisibilityNotPermittedNote) { if let VisibilityKind::Inherited = vis.kind { return; @@ -908,16 +895,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.walk_ty(ty) } - fn visit_label(&mut self, label: &'a Label) { - self.check_label(label.ident); - visit::walk_label(self, label); - } - - fn visit_lifetime(&mut self, lifetime: &'a Lifetime, _: visit::LifetimeCtxt) { - self.check_lifetime(lifetime.ident); - visit::walk_lifetime(self, lifetime); - } - fn visit_field_def(&mut self, field: &'a FieldDef) { self.deny_unnamed_field(field); visit::walk_field_def(self, field) @@ -1356,13 +1333,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - fn visit_generic_param(&mut self, param: &'a GenericParam) { - if let GenericParamKind::Lifetime { .. } = param.kind { - self.check_lifetime(param.ident); - } - visit::walk_generic_param(self, param); - } - fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) { match bound { GenericBound::Trait(trait_ref, modifiers) => { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 2c18b47f0f7..460da254653 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -10,21 +10,6 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::fluent_generated as fluent; #[derive(Diagnostic)] -#[diag(ast_passes_keyword_lifetime)] -pub struct KeywordLifetime { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_invalid_label)] -pub struct InvalidLabel { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] #[diag(ast_passes_visibility_not_permitted, code = E0449)] pub struct VisibilityNotPermitted { #[primary_span] diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 8bf3e670ff2..4cd0d9cb294 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,7 +1,7 @@ use rustc_errors::Diag; use rustc_hir::def_id::LocalDefId; +use rustc_infer::error_reporting::infer::nice_region_error::NiceRegionError; use rustc_infer::infer::canonical::Canonical; -use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::RegionVariableOrigin; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 55147ee337f..6cf797b4761 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -10,11 +10,11 @@ use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; use rustc_hir::WherePredicate::BoundPredicate; use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate}; -use rustc_infer::infer::error_reporting::nice_region_error::{ +use rustc_infer::error_reporting::infer::nice_region_error::{ self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params, HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, }; -use rustc_infer::infer::error_reporting::region::unexpected_hidden_region_diagnostic; +use rustc_infer::error_reporting::infer::region::unexpected_hidden_region_diagnostic; use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 3f23e0d9e04..1935005a08c 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use rustc_codegen_ssa::back::archive::{ - get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, + ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, }; use rustc_session::Session; @@ -9,7 +9,7 @@ pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> { - Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) + Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) } fn create_dll_import_lib( diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 73ff0c37b66..21676f5dbb6 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use rustc_codegen_ssa::back::archive::{ - get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, + ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, }; use rustc_session::Session; @@ -11,7 +11,7 @@ pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> { - Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) + Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) } fn create_dll_import_lib( diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index a354f3d3536..f46c6b1c498 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -15,8 +15,8 @@ use crate::errors::{ use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ - get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder, - ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, + try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, + ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER, }; use tracing::trace; @@ -115,7 +115,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { if true { Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) } else { - Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols)) + Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER)) } } @@ -291,59 +291,84 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { // The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files. // As such we need to use LLVM for them. + +static LLVM_OBJECT_READER: ObjectReader = ObjectReader { + get_symbols: get_llvm_object_symbols, + is_64_bit_object_file: llvm_is_64_bit_object_file, + is_ec_object_file: llvm_is_ec_object_file, + get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment, +}; + +fn should_use_llvm_reader(buf: &[u8]) -> bool { + let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) }; + + // COFF bigobj file, msvc LTO file or import library. See + // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51 + let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF"); + + is_bitcode || is_unsupported_windows_obj_file +} + #[deny(unsafe_op_in_unsafe_fn)] fn get_llvm_object_symbols( buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>, ) -> io::Result<bool> { - let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) }; + if !should_use_llvm_reader(buf) { + return (DEFAULT_OBJECT_READER.get_symbols)(buf, f); + } - // COFF bigobj file, msvc LTO file or import library. See - // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51 - let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF"); + let mut state = Box::new(f); - if is_bitcode || is_unsupported_windows_obj_file { - let mut state = Box::new(f); - - let err = unsafe { - llvm::LLVMRustGetSymbols( - buf.as_ptr(), - buf.len(), - std::ptr::addr_of_mut!(*state) as *mut c_void, - callback, - error_callback, - ) - }; + let err = unsafe { + llvm::LLVMRustGetSymbols( + buf.as_ptr(), + buf.len(), + std::ptr::addr_of_mut!(*state) as *mut c_void, + callback, + error_callback, + ) + }; - if err.is_null() { - return Ok(true); - } else { - return Err(unsafe { *Box::from_raw(err as *mut io::Error) }); - } + if err.is_null() { + return Ok(true); + } else { + return Err(unsafe { *Box::from_raw(err as *mut io::Error) }); + } - unsafe extern "C" fn callback( - state: *mut c_void, - symbol_name: *const c_char, - ) -> *mut c_void { - let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) }; - match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) { - Ok(()) => std::ptr::null_mut(), - Err(err) => Box::into_raw(Box::new(err)) as *mut c_void, - } + unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void { + let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) }; + match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) { + Ok(()) => std::ptr::null_mut(), + Err(err) => Box::into_raw(Box::new(err)) as *mut c_void, } + } - unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void { - let error = unsafe { CStr::from_ptr(error) }; - Box::into_raw(Box::new(io::Error::new( - io::ErrorKind::Other, - format!("LLVM error: {}", error.to_string_lossy()), - ))) as *mut c_void - } - } else { - get_native_object_symbols(buf, f) + unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void { + let error = unsafe { CStr::from_ptr(error) }; + Box::into_raw(Box::new(io::Error::new( + io::ErrorKind::Other, + format!("LLVM error: {}", error.to_string_lossy()), + ))) as *mut c_void } } +fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool { + if !should_use_llvm_reader(buf) { + return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf); + } + + unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) } +} + +fn llvm_is_ec_object_file(buf: &[u8]) -> bool { + if !should_use_llvm_reader(buf) { + return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf); + } + + unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) } +} + impl<'a> LlvmArchiveBuilder<'a> { fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> { let kind = &*self.sess.target.archive_format; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index e0bf6110cdf..ae46200d3f5 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2440,4 +2440,8 @@ extern "C" { callback: GetSymbolsCallback, error_callback: GetSymbolsErrorCallback, ) -> *mut c_void; + + pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool; + + pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool; } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 3771fc6b0a2..f7b5b0f310b 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -ar_archive_writer = "0.2.0" +ar_archive_writer = "0.3.0" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" cc = "1.0.90" diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index c99118f5156..ae649cd77c4 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -6,8 +6,8 @@ use rustc_span::symbol::Symbol; use super::metadata::search_for_section; -pub use ar_archive_writer::get_native_object_symbols; use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember}; +pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER}; use object::read::archive::ArchiveFile; use object::read::macho::FatArch; use tempfile::Builder as TempFileBuilder; @@ -89,8 +89,7 @@ pub trait ArchiveBuilder { #[must_use = "must call build() to finish building the archive"] pub struct ArArchiveBuilder<'a> { sess: &'a Session, - get_object_symbols: - fn(buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>) -> io::Result<bool>, + object_reader: &'static ObjectReader, src_archives: Vec<(PathBuf, Mmap)>, // Don't use an `HashMap` here, as the order is important. `lib.rmeta` needs @@ -105,14 +104,8 @@ enum ArchiveEntry { } impl<'a> ArArchiveBuilder<'a> { - pub fn new( - sess: &'a Session, - get_object_symbols: fn( - buf: &[u8], - f: &mut dyn FnMut(&[u8]) -> io::Result<()>, - ) -> io::Result<bool>, - ) -> ArArchiveBuilder<'a> { - ArArchiveBuilder { sess, get_object_symbols, src_archives: vec![], entries: vec![] } + pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchiveBuilder<'a> { + ArArchiveBuilder { sess, object_reader, src_archives: vec![], entries: vec![] } } } @@ -267,7 +260,7 @@ impl<'a> ArArchiveBuilder<'a> { entries.push(NewArchiveMember { buf: data, - get_symbols: self.get_object_symbols, + object_reader: self.object_reader, member_name: String::from_utf8(entry_name).unwrap(), mtime: 0, uid: 0, @@ -294,7 +287,13 @@ impl<'a> ArArchiveBuilder<'a> { let mut archive_tmpfile = File::create_new(&archive_tmpfile_path) .map_err(|err| io_error_context("couldn't create the temp file", err))?; - write_archive_to_stream(&mut archive_tmpfile, &entries, archive_kind, false)?; + write_archive_to_stream( + &mut archive_tmpfile, + &entries, + archive_kind, + false, + /* is_ec = */ self.sess.target.arch == "arm64ec", + )?; let any_entries = !entries.is_empty(); drop(entries); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 6a36938dd1d..9fef31acef8 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -82,7 +82,7 @@ use rustc_errors::{pluralize, struct_span_code_err, Diag}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::BitSet; -use rustc_infer::infer::error_reporting::ObligationCauseExt as _; +use rustc_infer::error_reporting::infer::ObligationCauseExt as _; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index ea9567f4e3d..6da3f1dd114 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::hir_ty_lowering::{ GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; -use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; +use rustc_infer::infer::need_type_info::TypeAnnotationNeeded; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; @@ -1519,7 +1519,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { let e = self.tainted_by_errors().unwrap_or_else(|| { self.err_ctxt() - .emit_inference_failure_err(self.body_id, sp, ty.into(), E0282, true) + .emit_inference_failure_err( + self.body_id, + sp, + ty.into(), + TypeAnnotationNeeded::E0282, + true, + ) .emit() }); let err = Ty::new_error(self.tcx, e); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 9fbb01216bb..b6b1bf34653 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -29,7 +29,7 @@ use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_index::IndexVec; -use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; +use rustc_infer::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::TypeTrace; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::adjustment::AllowTwoPhase; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b5796fbd48a..3fe87c03e74 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -15,9 +15,9 @@ use hir::def_id::CRATE_DEF_ID; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; +use rustc_infer::error_reporting::infer::sub_relations::SubRelations; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_infer::infer; -use rustc_infer::infer::error_reporting::sub_relations::SubRelations; -use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::symbol::Ident; diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index dc1b888374c..daf4ef5cdb3 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -182,8 +182,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_expr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> { - let pick = - self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?; + let scope = if let Some(only_method) = segment.res.opt_def_id() { + ProbeScope::Single(only_method) + } else { + ProbeScope::TraitsInScope + }; + + let pick = self.lookup_probe(segment.ident, self_ty, call_expr, scope)?; self.lint_edition_dependent_dot_call( self_ty, segment, span, call_expr, self_expr, &pick, args, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6a7af5510e0..e817685e41c 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -12,7 +12,7 @@ use rustc_hir::HirId; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; -use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; +use rustc_infer::infer::need_type_info::TypeAnnotationNeeded; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCauseCode; @@ -20,6 +20,7 @@ use rustc_middle::middle::stability; use rustc_middle::query::Providers; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; +use rustc_middle::ty::AssocItemContainer; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::Upcast; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; @@ -216,6 +217,9 @@ pub enum Mode { #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum ProbeScope { + // Single candidate coming from pre-resolved delegation method. + Single(DefId), + // Assemble candidates coming only from traits in scope. TraitsInScope, @@ -441,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.body_id, span, ty.into(), - E0282, + TypeAnnotationNeeded::E0282, !raw_ptr_call, ); if raw_ptr_call { @@ -480,12 +484,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_suggestion, ); - probe_cx.assemble_inherent_candidates(); match scope { ProbeScope::TraitsInScope => { - probe_cx.assemble_extension_candidates_for_traits_in_scope() + probe_cx.assemble_inherent_candidates(); + probe_cx.assemble_extension_candidates_for_traits_in_scope(); + } + ProbeScope::AllTraits => { + probe_cx.assemble_inherent_candidates(); + probe_cx.assemble_extension_candidates_for_all_traits(); + } + ProbeScope::Single(def_id) => { + let item = self.tcx.associated_item(def_id); + // FIXME(fn_delegation): Delegation to inherent methods is not yet supported. + assert_eq!(item.container, AssocItemContainer::TraitContainer); + + let trait_def_id = self.tcx.parent(def_id); + let trait_span = self.tcx.def_span(trait_def_id); + + let trait_args = self.fresh_args_for_item(trait_span, trait_def_id); + let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args); + + probe_cx.push_candidate( + Candidate { + item, + kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)), + import_ids: smallvec![], + }, + false, + ); } - ProbeScope::AllTraits => probe_cx.assemble_extension_candidates_for_all_traits(), }; op(probe_cx) }) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index e800c1a97d9..611854ce2af 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -8,7 +8,7 @@ use rustc_errors::{ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; -use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; +use rustc_infer::infer::need_type_info::TypeAnnotationNeeded; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; @@ -783,7 +783,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { self.fcx.tcx.hir().body_owner_def_id(self.body.id()), self.span.to_span(self.fcx.tcx), p.into(), - E0282, + TypeAnnotationNeeded::E0282, false, ) .emit() diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/mod.rs index bb1285ee813..ddd5818203c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/mod.rs @@ -45,17 +45,11 @@ //! ported to this system, and which relies on string concatenation at the //! time of error detection. -use super::{InferCtxt, TypeTrace, ValuePairs}; - -use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags}; -use crate::infer; -use crate::infer::ExpectedFound; -use crate::traits::{ - IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, - PredicateObligation, -}; +use std::borrow::Cow; +use std::ops::{ControlFlow, Deref}; +use std::path::PathBuf; +use std::{cmp, fmt, iter}; -use crate::infer::relate::{self, RelateResult, TypeRelation}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{ pluralize, Applicability, Diag, DiagCtxtHandle, DiagStyledString, IntoDiagArg, StringPart, @@ -68,6 +62,7 @@ use rustc_hir::{self as hir}; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; +use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _}; use rustc_middle::ty::{ @@ -76,18 +71,21 @@ use rustc_middle::ty::{ }; use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; -use std::borrow::Cow; -use std::ops::{ControlFlow, Deref}; -use std::path::PathBuf; -use std::{cmp, fmt, iter}; + +use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags}; +use crate::infer; +use crate::infer::relate::{self, RelateResult, TypeRelation}; +use crate::infer::{InferCtxt, TypeTrace, ValuePairs}; +use crate::traits::{ + IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, + PredicateObligation, +}; mod note_and_explain; mod suggest; -pub(crate) mod need_type_info; -pub mod sub_relations; -pub use need_type_info::TypeAnnotationNeeded; pub mod region; +pub mod sub_relations; pub mod nice_region_error; @@ -1242,7 +1240,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(values) => { let values = self.resolve_vars_if_possible(values); let (is_simple_error, exp_found) = match values { - ValuePairs::Terms(infer::ExpectedFound { expected, found }) => { + ValuePairs::Terms(ExpectedFound { expected, found }) => { match (expected.unpack(), found.unpack()) { (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { let is_simple_err = expected.is_simple_text(self.tcx) @@ -1254,7 +1252,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ( is_simple_err, - Mismatch::Variable(infer::ExpectedFound { expected, found }), + Mismatch::Variable(ExpectedFound { expected, found }), ) } (ty::TermKind::Const(_), ty::TermKind::Const(_)) => { @@ -1263,13 +1261,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => (false, Mismatch::Fixed("type")), } } - ValuePairs::PolySigs(infer::ExpectedFound { expected, found }) => { + ValuePairs::PolySigs(ExpectedFound { expected, found }) => { OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span) .report(diag); (false, Mismatch::Fixed("signature")) } ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")), - ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => { + ValuePairs::Aliases(ExpectedFound { expected, .. }) => { (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id))) } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), @@ -1303,9 +1301,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some((sp, msg)) = secondary_span { if swap_secondary_and_primary { - let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound { - expected, - .. + let terr = if let Some(infer::ValuePairs::Terms(ExpectedFound { + expected, .. })) = values { Cow::from(format!("expected this to be `{expected}`")) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs index cbeec591960..74dcde03639 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs @@ -1,21 +1,20 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where both the regions are anonymous. +use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type; +use crate::error_reporting::infer::nice_region_error::util::AnonymousParamInfo; +use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::errors::AddLifetimeParamsSuggestion; use crate::errors::LifetimeMismatch; use crate::errors::LifetimeMismatchLabels; -use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; -use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::RegionResolutionError; use crate::infer::SubregionOrigin; -use crate::infer::TyCtxt; use rustc_errors::Subdiagnostic; use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::def_id::LocalDefId; use rustc_hir::Ty; -use rustc_middle::ty::Region; +use rustc_middle::ty::{Region, TyCtxt}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when both the concerned regions are anonymous. diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs index b91b755d683..b91b755d683 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs index 7996b4bf65b..550cc455e01 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs @@ -1,12 +1,12 @@ //! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate //! to hold. +use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq}; use crate::errors::{ DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime, }; -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::ObligationCauseCode; use rustc_data_structures::fx::FxIndexSet; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs index cffdfa88752..ced4c384f02 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs @@ -1,6 +1,6 @@ -use crate::infer::error_reporting::TypeErrCtxt; -use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::infer::lexical_region_resolve::RegionResolutionError::*; +use crate::error_reporting::infer::TypeErrCtxt; +use crate::infer::RegionResolutionError; +use crate::infer::RegionResolutionError::*; use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 85624c9ca73..d1802d2f5ee 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -1,11 +1,9 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where one region is named and the other is anonymous. -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::{ - errors::ExplicitLifetimeRequired, - infer::error_reporting::nice_region_error::find_anon_type::find_anon_type, -}; +use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type; +use crate::error_reporting::infer::nice_region_error::NiceRegionError; +use crate::errors::ExplicitLifetimeRequired; use rustc_errors::Diag; use rustc_middle::ty; use rustc_span::symbol::kw; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 80b7e3b4fa5..476ac3f1720 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -1,9 +1,9 @@ +use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::errors::{ ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, TraitPlaceholderMismatch, TyOrSig, }; -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::RegionResolutionError; use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index a3f306802de..e9f17a3e3e2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -1,9 +1,6 @@ -use crate::{ - errors::PlaceholderRelationLfNotSatisfied, - infer::{ - error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin, - }, -}; +use crate::error_reporting::infer::nice_region_error::NiceRegionError; +use crate::errors::PlaceholderRelationLfNotSatisfied; +use crate::infer::{RegionResolutionError, SubregionOrigin}; use rustc_data_structures::intern::Interned; use rustc_errors::Diag; use rustc_middle::ty::{self, RePlaceholder, Region}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 9973646aecd..ce157ff3dc8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -1,11 +1,11 @@ //! Error Reporting for static impl Traits. +use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::errors::{ ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted, ReqIntroducedLocations, }; -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_data_structures::fx::FxIndexSet; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 7f3e23716f9..c58c7e13551 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -1,8 +1,8 @@ //! Error Reporting for `impl` items that do not match the obligations from their `trait`. +use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::RegionResolutionError; use crate::infer::{Subtype, ValuePairs}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs index 83145e4f7b2..30fa98c5526 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs @@ -1,13 +1,13 @@ //! Helper functions corresponding to lifetime errors due to //! anonymous regions. -use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::TyCtxt; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{self, Binder, Region, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; +use crate::error_reporting::infer::nice_region_error::NiceRegionError; + /// Information about the anonymous region we are searching for. #[derive(Debug)] pub struct AnonymousParamInfo<'tcx> { diff --git a/compiler/rustc_infer/src/error_reporting/infer/note.rs b/compiler/rustc_infer/src/error_reporting/infer/note.rs new file mode 100644 index 00000000000..aeb3049c2ae --- /dev/null +++ b/compiler/rustc_infer/src/error_reporting/infer/note.rs @@ -0,0 +1,421 @@ +use crate::error_reporting::infer::{note_and_explain_region, TypeErrCtxt}; +use crate::errors::{ + note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, + RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, +}; +use crate::fluent_generated as fluent; +use crate::infer::{self, SubregionOrigin}; +use rustc_errors::{Diag, Subdiagnostic}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::traits::ObligationCauseCode; +use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::{self, IsSuggestable, Region, Ty}; +use rustc_span::symbol::kw; + +use super::ObligationCauseAsDiagArg; + +impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { + pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) { + match *origin { + infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { + span: trace.cause.span, + requirement: ObligationCauseAsDiagArg(trace.cause.clone()), + expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)), + } + .add_to_diag(err), + infer::Reborrow(span) => { + RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err) + } + infer::RelateObjectBound(span) => { + RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } + .add_to_diag(err); + } + infer::ReferenceOutlivesReferent(ty, span) => { + RegionOriginNote::WithName { + span, + msg: fluent::infer_reference_outlives_referent, + name: &self.ty_to_string(ty), + continues: false, + } + .add_to_diag(err); + } + infer::RelateParamBound(span, ty, opt_span) => { + RegionOriginNote::WithName { + span, + msg: fluent::infer_relate_param_bound, + name: &self.ty_to_string(ty), + continues: opt_span.is_some(), + } + .add_to_diag(err); + if let Some(span) = opt_span { + RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } + .add_to_diag(err); + } + } + infer::RelateRegionParamBound(span) => { + RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } + .add_to_diag(err); + } + infer::CompareImplItemObligation { span, .. } => { + RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } + .add_to_diag(err); + } + infer::CheckAssociatedTypeBounds { ref parent, .. } => { + self.note_region_origin(err, parent); + } + infer::AscribeUserTypeProvePredicate(span) => { + RegionOriginNote::Plain { + span, + msg: fluent::infer_ascribe_user_type_prove_predicate, + } + .add_to_diag(err); + } + } + } + + pub(super) fn report_concrete_failure( + &self, + generic_param_scope: LocalDefId, + origin: SubregionOrigin<'tcx>, + sub: Region<'tcx>, + sup: Region<'tcx>, + ) -> Diag<'a> { + let mut err = match origin { + infer::Subtype(box trace) => { + let terr = TypeError::RegionsDoesNotOutlive(sup, sub); + let mut err = self.report_and_explain_type_error(trace, terr); + match (*sub, *sup) { + (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} + (ty::RePlaceholder(_), _) => { + note_and_explain_region( + self.tcx, + &mut err, + generic_param_scope, + "", + sup, + " doesn't meet the lifetime requirements", + None, + ); + } + (_, ty::RePlaceholder(_)) => { + note_and_explain_region( + self.tcx, + &mut err, + generic_param_scope, + "the required lifetime does not necessarily outlive ", + sub, + "", + None, + ); + } + _ => { + note_and_explain_region( + self.tcx, + &mut err, + generic_param_scope, + "", + sup, + "...", + None, + ); + note_and_explain_region( + self.tcx, + &mut err, + generic_param_scope, + "...does not necessarily outlive ", + sub, + "", + None, + ); + } + } + err + } + infer::Reborrow(span) => { + let reference_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + None, + note_and_explain::PrefixKind::RefValidFor, + note_and_explain::SuffixKind::Continues, + ); + let content_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sup, + None, + note_and_explain::PrefixKind::ContentValidFor, + note_and_explain::SuffixKind::Empty, + ); + self.dcx().create_err(OutlivesContent { + span, + notes: reference_valid.into_iter().chain(content_valid).collect(), + }) + } + infer::RelateObjectBound(span) => { + let object_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + None, + note_and_explain::PrefixKind::TypeObjValidFor, + note_and_explain::SuffixKind::Empty, + ); + let pointer_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sup, + None, + note_and_explain::PrefixKind::SourcePointerValidFor, + note_and_explain::SuffixKind::Empty, + ); + self.dcx().create_err(OutlivesBound { + span, + notes: object_valid.into_iter().chain(pointer_valid).collect(), + }) + } + infer::RelateParamBound(span, ty, opt_span) => { + let prefix = match *sub { + ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy, + _ => note_and_explain::PrefixKind::TypeOutlive, + }; + let suffix = if opt_span.is_some() { + note_and_explain::SuffixKind::ReqByBinding + } else { + note_and_explain::SuffixKind::Empty + }; + let note = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + opt_span, + prefix, + suffix, + ); + self.dcx().create_err(FulfillReqLifetime { + span, + ty: self.resolve_vars_if_possible(ty), + note, + }) + } + infer::RelateRegionParamBound(span) => { + let param_instantiated = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sup, + None, + note_and_explain::PrefixKind::LfParamInstantiatedWith, + note_and_explain::SuffixKind::Empty, + ); + let param_must_outlive = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + None, + note_and_explain::PrefixKind::LfParamMustOutlive, + note_and_explain::SuffixKind::Empty, + ); + self.dcx().create_err(LfBoundNotSatisfied { + span, + notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), + }) + } + infer::ReferenceOutlivesReferent(ty, span) => { + let pointer_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + None, + note_and_explain::PrefixKind::PointerValidFor, + note_and_explain::SuffixKind::Empty, + ); + let data_valid = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sup, + None, + note_and_explain::PrefixKind::DataValidFor, + note_and_explain::SuffixKind::Empty, + ); + self.dcx().create_err(RefLongerThanData { + span, + ty: self.resolve_vars_if_possible(ty), + notes: pointer_valid.into_iter().chain(data_valid).collect(), + }) + } + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { + let mut err = self.infcx.report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{sup}: {sub}`"), + ); + // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause + if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) + && generics.where_clause_span.contains(span) + { + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); + } + err + } + infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { + let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup); + + // Don't mention the item name if it's an RPITIT, since that'll just confuse + // folks. + if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) { + let trait_item_span = self.tcx.def_span(trait_item_def_id); + let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); + err.span_label( + trait_item_span, + format!("definition of `{item_name}` from trait"), + ); + } + + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); + err + } + infer::AscribeUserTypeProvePredicate(span) => { + let instantiated = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sup, + None, + note_and_explain::PrefixKind::LfInstantiatedWith, + note_and_explain::SuffixKind::Empty, + ); + let must_outlive = note_and_explain::RegionExplanation::new( + self.tcx, + generic_param_scope, + sub, + None, + note_and_explain::PrefixKind::LfMustOutlive, + note_and_explain::SuffixKind::Empty, + ); + self.dcx().create_err(LfBoundNotSatisfied { + span, + notes: instantiated.into_iter().chain(must_outlive).collect(), + }) + } + }; + if sub.is_error() || sup.is_error() { + err.downgrade_to_delayed_bug(); + } + err + } + + pub fn suggest_copy_trait_method_bounds( + &self, + trait_item_def_id: DefId, + impl_item_def_id: LocalDefId, + err: &mut Diag<'_>, + ) { + // FIXME(compiler-errors): Right now this is only being used for region + // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, + // but right now it's not really very smart when it comes to implicit `Sized` + // predicates and bounds on the trait itself. + + let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) + else { + return; + }; + let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else { + return; + }; + let trait_args = trait_ref + .instantiate_identity() + // Replace the explicit self type with `Self` for better suggestion rendering + .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper)) + .args; + let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id) + .rebase_onto(self.tcx, impl_def_id, trait_args); + + let Ok(trait_predicates) = + self.tcx + .explicit_predicates_of(trait_item_def_id) + .instantiate_own(self.tcx, trait_item_args) + .map(|(pred, _)| { + if pred.is_suggestable(self.tcx, false) { + Ok(pred.to_string()) + } else { + Err(()) + } + }) + .collect::<Result<Vec<_>, ()>>() + else { + return; + }; + + let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { + return; + }; + + let suggestion = if trait_predicates.is_empty() { + WhereClauseSuggestions::Remove { span: generics.where_clause_span } + } else { + let space = if generics.where_clause_span.is_empty() { " " } else { "" }; + WhereClauseSuggestions::CopyPredicates { + span: generics.where_clause_span, + space, + trait_predicates: trait_predicates.join(", "), + } + }; + err.subdiagnostic(suggestion); + } + + pub(super) fn report_placeholder_failure( + &self, + generic_param_scope: LocalDefId, + placeholder_origin: SubregionOrigin<'tcx>, + sub: Region<'tcx>, + sup: Region<'tcx>, + ) -> Diag<'a> { + // I can't think how to do better than this right now. -nikomatsakis + debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); + match placeholder_origin { + infer::Subtype(box ref trace) + if matches!( + &trace.cause.code().peel_derives(), + ObligationCauseCode::WhereClause(..) + | ObligationCauseCode::WhereClauseInExpr(..) + ) => + { + // Hack to get around the borrow checker because trace.cause has an `Rc`. + if let ObligationCauseCode::WhereClause(_, span) + | ObligationCauseCode::WhereClauseInExpr(_, span, ..) = + &trace.cause.code().peel_derives() + && !span.is_dummy() + { + let span = *span; + self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup) + .with_span_note(span, "the lifetime requirement is introduced here") + } else { + unreachable!( + "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..." + ) + } + } + infer::Subtype(box trace) => { + let terr = TypeError::RegionsPlaceholderMismatch; + return self.report_and_explain_type_error(trace, terr); + } + _ => { + return self.report_concrete_failure( + generic_param_scope, + placeholder_origin, + sub, + sup, + ); + } + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs index d5e7de897d0..d5e7de897d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs diff --git a/compiler/rustc_infer/src/infer/error_reporting/region.rs b/compiler/rustc_infer/src/error_reporting/infer/region.rs index 191cb23184d..093d2d3d743 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/region.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/region.rs @@ -18,12 +18,12 @@ use rustc_type_ir::Upcast as _; use super::nice_region_error::find_anon_type; use super::{nice_region_error, ObligationCauseAsDiagArg}; +use crate::error_reporting::infer::{ObligationCauseExt as _, TypeErrCtxt}; use crate::errors::{ self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, }; use crate::fluent_generated as fluent; -use crate::infer::error_reporting::{ObligationCauseExt as _, TypeErrCtxt}; use crate::infer::region_constraints::GenericKind; use crate::infer::{self, InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs b/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs index ef26a8ff7b8..ef26a8ff7b8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/error_reporting/infer/suggest.rs index 13b145296a7..4d11ab9fac6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/suggest.rs @@ -1,4 +1,4 @@ -use crate::infer::error_reporting::hir::Path; +use crate::error_reporting::infer::hir::Path; use core::ops::ControlFlow; use hir::def::CtorKind; use hir::intravisit::{walk_expr, walk_stmt, Visitor}; diff --git a/compiler/rustc_infer/src/error_reporting/mod.rs b/compiler/rustc_infer/src/error_reporting/mod.rs new file mode 100644 index 00000000000..132485ec661 --- /dev/null +++ b/compiler/rustc_infer/src/error_reporting/mod.rs @@ -0,0 +1 @@ +pub mod infer; diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index ce1b0f86d03..f849a1a7322 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -15,11 +15,10 @@ use rustc_span::symbol::kw; use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; +use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; +use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::fluent_generated as fluent; -use crate::infer::error_reporting::{ - need_type_info::UnderspecifiedArgKind, nice_region_error::placeholder_error::Highlighted, - ObligationCauseAsDiagArg, -}; +use crate::infer::need_type_info::UnderspecifiedArgKind; use std::path::PathBuf; diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 4fbeb0ec102..d71b7f3c264 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,5 +1,5 @@ +use crate::error_reporting::infer::nice_region_error::find_anon_type; use crate::fluent_generated as fluent; -use crate::infer::error_reporting::nice_region_error::find_anon_type; use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a0be545d46f..cfef1f13015 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -11,9 +11,9 @@ pub use BoundRegionConversionTime::*; pub use RegionVariableOrigin::*; pub use SubregionOrigin::*; +use crate::error_reporting::infer::TypeErrCtxt; use crate::infer::relate::RelateResult; use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; -use error_reporting::TypeErrCtxt; use free_regions::RegionRelations; use lexical_region_resolve::LexicalRegionResolutions; use opaque_types::OpaqueTypeStorage; @@ -54,7 +54,6 @@ use type_variable::TypeVariableOrigin; pub mod at; pub mod canonical; mod context; -pub mod error_reporting; pub mod free_regions; mod freshen; mod lexical_region_resolve; @@ -66,6 +65,8 @@ pub mod relate; pub mod resolve; pub(crate) mod snapshot; pub mod type_variable; +// FIXME(error_reporting): Where should we put this? +pub mod need_type_info; #[must_use] #[derive(Debug)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/need_type_info.rs index 084aebc296f..4f3dcd9043f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/need_type_info.rs @@ -1,8 +1,8 @@ +use crate::error_reporting::infer::TypeErrCtxt; use crate::errors::{ AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, SourceKindMultiSuggestion, SourceKindSubdiag, }; -use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::InferCtxt; use rustc_errors::{codes::*, Diag, IntoDiagArg}; use rustc_hir as hir; diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index b65ac859667..02ebf933f53 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -34,6 +34,7 @@ #[macro_use] extern crate tracing; +pub mod error_reporting; mod errors; pub mod infer; pub mod traits; diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index a9d1362a338..ccf1a5429e2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -4,12 +4,16 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // Derived from: -// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h -// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp +// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/include/llvm/Object/ArchiveWriter.h +// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/lib/Object/ArchiveWriter.cpp +#include "LLVMWrapper.h" #include "SuppressLLVMWarnings.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" #include <llvm/Support/raw_ostream.h> @@ -34,6 +38,27 @@ static bool isArchiveSymbol(const object::BasicSymbolRef &S) { typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *); typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *); +// This function is copied from ArchiveWriter.cpp. +static Expected<std::unique_ptr<SymbolicFile>> +getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) { + const file_magic Type = identify_magic(Buf.getBuffer()); + // Don't attempt to read non-symbolic file types. + if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) + return nullptr; + if (Type == file_magic::bitcode) { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + Buf, file_magic::bitcode, &Context); + if (!ObjOrErr) + return ObjOrErr.takeError(); + return std::move(*ObjOrErr); + } else { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf); + if (!ObjOrErr) + return ObjOrErr.takeError(); + return std::move(*ObjOrErr); + } +} + // Note: This is implemented in C++ instead of using the C api from Rust as // IRObjectFile doesn't implement getSymbolName, only printSymbolName, which is // inaccessible from the C api. @@ -49,36 +74,16 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. LLVMContext Context; - std::unique_ptr<object::SymbolicFile> Obj; - - const file_magic Type = identify_magic(Buf->getBuffer()); - if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) { - return 0; - } - - if (Type == file_magic::bitcode) { - auto ObjOrErr = object::SymbolicFile::createSymbolicFile( - Buf->getMemBufferRef(), file_magic::bitcode, &Context); - if (!ObjOrErr) { - Error E = ObjOrErr.takeError(); - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); - } - Obj = std::move(*ObjOrErr); - } else { - auto ObjOrErr = - object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); - if (!ObjOrErr) { - Error E = ObjOrErr.takeError(); - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); - } - Obj = std::move(*ObjOrErr); + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + auto Error = raw_svector_ostream(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); for (const object::BasicSymbolRef &S : Obj->symbols()) { if (!isArchiveSymbol(S)) @@ -97,3 +102,72 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, } return 0; } + +// Encoding true and false as invalid pointer values +#define TRUE_PTR (void *)1 +#define FALSE_PTR (void *)0 + +extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( + StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); + SmallString<0> SymNameBuf; + auto SymName = raw_svector_ostream(SymNameBuf); + + // Code starting from this line is copied from s64BitSymbolicFile in + // ArchiveWriter.cpp. + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + return false; + } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); + + return Obj != nullptr ? Obj->is64Bit() : false; +} + +extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) { + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( + StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); + SmallString<0> SymNameBuf; + auto SymName = raw_svector_ostream(SymNameBuf); + + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + return false; + } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); + + if (Obj == nullptr) { + return false; + } + + // Code starting from this line is copied from isECObject in + // ArchiveWriter.cpp with an extra #if to work with LLVM 17. + if (Obj->isCOFF()) + return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; + +#if LLVM_VERSION_GE(18, 0) + if (Obj->isCOFFImportFile()) + return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; +#endif + + if (Obj->isIR()) { + Expected<std::string> TripleStr = + getBitcodeTargetTriple(Obj->getMemoryBufferRef()); + if (!TripleStr) + return false; + Triple T(*TripleStr); + return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; + } + + return false; +} diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c2201b1c41e..4ce9e0f025c 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -388,6 +388,9 @@ parse_invalid_dyn_keyword = invalid `dyn` keyword parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` parse_invalid_identifier_with_leading_number = identifiers cannot start with a number +parse_invalid_label = + invalid label name `{$name}` + parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid .label = invalid suffix `{$suffix}` .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases @@ -414,6 +417,9 @@ parse_invalid_unicode_escape = invalid unicode character escape parse_invalid_variable_declaration = invalid variable declaration +parse_keyword_lifetime = + lifetimes cannot use keyword names + parse_kw_bad_case = keyword `{$kw}` is written in the wrong case .suggestion = write it in the correct case diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 092a2a10ab7..4222486034b 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2010,6 +2010,21 @@ pub struct CannotBeRawIdent { } #[derive(Diagnostic)] +#[diag(parse_keyword_lifetime)] +pub struct KeywordLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_invalid_label)] +pub struct InvalidLabel { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] #[diag(parse_cr_doc_comment)] pub struct CrDocComment { #[primary_span] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4bd20be4171..0ba8c66f48f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2932,10 +2932,17 @@ impl<'a> Parser<'a> { } pub(crate) fn eat_label(&mut self) -> Option<Label> { - self.token.lifetime().map(|ident| { + if let Some(ident) = self.token.lifetime() { + // Disallow `'fn`, but with a better error message than `expect_lifetime`. + if ident.without_first_quote().is_reserved() { + self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name }); + } + self.bump(); - Label { ident } - }) + Some(Label { ident }) + } else { + None + } } /// Parses a `match ... { ... }` expression (`match` token already eaten). diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 4a78b427832..41e31d76d62 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -177,8 +177,11 @@ impl<'a> Parser<'a> { .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) } NonterminalKind::Lifetime => { - return if self.check_lifetime() { - Ok(ParseNtResult::Lifetime(self.expect_lifetime().ident)) + // We want to keep `'keyword` parsing, just like `keyword` is still + // an ident for nonterminal purposes. + return if let Some(ident) = self.token.lifetime() { + self.bump(); + Ok(ParseNtResult::Lifetime(ident)) } else { Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e4e89615d71..8e8df9f0a84 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -542,12 +542,12 @@ impl<'a> Parser<'a> { None => PatKind::Path(qself, path), } } - } else if let token::Lifetime(lt) = self.token.kind + } else if let Some(lt) = self.token.lifetime() // In pattern position, we're totally fine with using "next token isn't colon" // as a heuristic. We could probably just always try to recover if it's a lifetime, // because we never have `'a: label {}` in a pattern position anyways, but it does // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..` - && could_be_unclosed_char_literal(Ident::with_dummy_span(lt)) + && could_be_unclosed_char_literal(lt) && !self.look_ahead(1, |token| matches!(token.kind, token::Colon)) { // Recover a `'a` as a `'a'` literal @@ -683,12 +683,12 @@ impl<'a> Parser<'a> { /// Parse `&pat` / `&mut pat`. fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> { self.expect_and()?; - if let token::Lifetime(name) = self.token.kind { + if let Some(lifetime) = self.token.lifetime() { self.bump(); // `'a` self.dcx().emit_err(UnexpectedLifetimeInPattern { span: self.prev_token.span, - symbol: name, + symbol: lifetime.name, suggestion: self.prev_token.span.until(self.token.span), }); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 94321b1dddd..68b8af7d20e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1230,6 +1230,12 @@ impl<'a> Parser<'a> { /// Parses a single lifetime `'a` or panics. pub(super) fn expect_lifetime(&mut self) -> Lifetime { if let Some(ident) = self.token.lifetime() { + if ident.without_first_quote().is_reserved() + && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name) + { + self.dcx().emit_err(errors::KeywordLifetime { span: ident.span }); + } + self.bump(); Lifetime { ident, id: ast::DUMMY_NODE_ID } } else { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 92cf73870ff..ced5ac17dac 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -316,7 +316,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn insert_field_def_ids(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef]) { + fn insert_field_idents(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef]) { if fields.iter().any(|field| field.is_placeholder) { // The fields are not expanded yet. return; @@ -652,7 +652,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let def_id = feed.key(); // Record field names for error reporting. - self.insert_field_def_ids(def_id, fields); + self.insert_field_idents(def_id, fields); self.insert_field_visibilities_local(def_id.to_def_id(), fields); for field in fields { @@ -1520,7 +1520,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // Record field names for error reporting. - self.insert_field_def_ids(def_id, variant.data.fields()); + self.insert_field_idents(def_id, variant.data.fields()); self.insert_field_visibilities_local(def_id.to_def_id(), variant.data.fields()); visit::walk_variant(self, variant); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index c301deac616..deab0451ccb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -8,7 +8,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor as _; use rustc_hir::LangItem; -use rustc_infer::infer::error_reporting::{TypeAnnotationNeeded, TypeErrCtxt}; +use rustc_infer::error_reporting::infer::TypeErrCtxt; +use rustc_infer::infer::need_type_info::TypeAnnotationNeeded; use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt}; use rustc_infer::traits::util::elaborate; use rustc_infer::traits::{ diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 2e6247b4640..0d040ddbacb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -4,7 +4,6 @@ use crate::error_reporting::traits::infer_ctxt_ext::InferCtxtExt; use crate::errors::{ AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, }; -use crate::infer::error_reporting::TyCategory; use crate::infer::InferCtxtExt as _; use crate::infer::{self, InferCtxt}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -25,7 +24,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; use rustc_hir::{self as hir, LangItem}; -use rustc_infer::infer::error_reporting::TypeErrCtxt; +use rustc_infer::error_reporting::infer::TyCategory; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_macros::extension; use rustc_middle::traits::select::OverflowError; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 2131e236401..16dfa27b75a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, LangItem}; -use rustc_infer::infer::error_reporting::TypeErrCtxt; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_infer::traits::{ Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index e90fe8fb94d..a448e1924c8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -3,7 +3,6 @@ use crate::error_reporting::traits::fulfillment_errors::InferCtxtPrivExt; use crate::errors::{ EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, }; -use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::InferCtxtExt; use rustc_ast::AttrArgs; use rustc_ast::AttrArgsEq; @@ -14,6 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_macros::{extension, LintDiagnostic}; use rustc_middle::bug; use rustc_middle::ty::print::PrintTraitRefExt as _; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index 061a5a4be20..fe1771f9096 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -5,7 +5,7 @@ use rustc_errors::{ }; use rustc_hir::def::Namespace; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_infer::infer::error_reporting::TypeErrCtxt; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_macros::extension; use rustc_middle::ty::print::{FmtPrinter, Print}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 2bf582dcfb1..fa2acdd4a54 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -23,7 +23,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node}; -use rustc_infer::infer::error_reporting::TypeErrCtxt; +use rustc_infer::error_reporting::infer::TypeErrCtxt; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_macros::extension; use rustc_middle::hir::map; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index ba2ad53a94e..d4dd3e546ec 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1820,6 +1820,21 @@ impl Step for Assemble { &self_contained_lld_dir.join(exe(name, target_compiler.host)), ); } + + // In addition to `rust-lld` also install `wasm-component-ld` when + // LLD is enabled. This is a relatively small binary that primarily + // delegates to the `rust-lld` binary for linking and then runs + // logic to create the final binary. This is used by the + // `wasm32-wasip2` target of Rust. + let wasm_component_ld_exe = + builder.ensure(crate::core::build_steps::tool::WasmComponentLd { + compiler: build_compiler, + target: target_compiler.host, + }); + builder.copy_link( + &wasm_component_ld_exe, + &libdir_bin.join(wasm_component_ld_exe.file_name().unwrap()), + ); } if builder.config.llvm_enabled(target_compiler.host) { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index ad92a01bce7..7bc410b9e88 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -337,6 +337,7 @@ bootstrap_tool!( RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; CoverageDump, "src/tools/coverage-dump", "coverage-dump"; RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper"; + WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization"; ); #[derive(Debug, Clone, Hash, PartialEq, Eq)] diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index e3cb396b782..962484593b4 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -112,6 +112,7 @@ ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,wasm32-wasip1 ENV TARGETS=$TARGETS,wasm32-wasip1-threads +ENV TARGETS=$TARGETS,wasm32-wasip2 ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 diff --git a/src/tools/clippy/tests/ui/track-diagnostics.stderr b/src/tools/clippy/tests/ui/track-diagnostics.stderr index 410e80f2528..3c7577dd003 100644 --- a/src/tools/clippy/tests/ui/track-diagnostics.stderr +++ b/src/tools/clippy/tests/ui/track-diagnostics.stderr @@ -3,7 +3,7 @@ error[E0308]: mismatched types | LL | const S: A = B; | ^ expected `A`, found `B` --Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC +-Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC error: aborting due to 1 previous error diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 08d28e58166..e6376a8df0f 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -96,9 +96,7 @@ run-make/print-target-list/Makefile run-make/prune-link-args/Makefile run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile -run-make/raw-dylib-custom-dlltool/Makefile run-make/raw-dylib-import-name-type/Makefile -run-make/raw-dylib-inline-cross-dylib/Makefile run-make/raw-dylib-link-ordinal/Makefile run-make/raw-dylib-stdcall-ordinal/Makefile run-make/redundant-libs/Makefile diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c72fae0881..f9bf04626f7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -95,7 +95,12 @@ const EXCEPTIONS: ExceptionList = &[ ("self_cell", "Apache-2.0"), // rustc (fluent translations) ("snap", "BSD-3-Clause"), // rustc ("wasm-encoder", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wasm-metadata", "Apache-2.0 WITH LLVM-exception"), // rustc ("wasmparser", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wast", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wat", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wit-component", "Apache-2.0 WITH LLVM-exception"), // rustc + ("wit-parser", "Apache-2.0 WITH LLVM-exception"), // rustc // tidy-alphabetical-end ]; diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml new file mode 100644 index 00000000000..91ff19ad9fc --- /dev/null +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -0,0 +1,13 @@ +# See the `README.md` in this directory for what this tool is. + +[package] +name = "wasm-component-ld-wrapper" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "wasm-component-ld" +path = "src/main.rs" + +[dependencies] +wasm-component-ld = "0.5.4" diff --git a/src/tools/wasm-component-ld/README.md b/src/tools/wasm-component-ld/README.md new file mode 100644 index 00000000000..54608a2dea1 --- /dev/null +++ b/src/tools/wasm-component-ld/README.md @@ -0,0 +1,62 @@ +# `wasm-component-ld` + +This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate. That +crate. That crate is itself a thin wrapper around two pieces: + +* `wasm-ld` - the LLVM-based linker distributed as part of LLD and packaged in + Rust as `rust-lld`. +* [`wit-component`] - a Rust crate for creating a [WebAssembly Component] from a + core wasm module. + +This linker is used for Rust's `wasm32-wasip2` target to natively output a +component instead of a core WebAssembly module, unlike other WebAssembly +targets. If you're confused about any of this here's an FAQ-style explanation of +what's going on here: + +* **What's a component?** - It's a proposal to the WebAssembly standard + primarily developed at this time by out-of-browser use cases of WebAssembly. + You can find high-level documentation [here][component docs]. + +* **What's WASIp2?** - Not to be confused with WASIp1, WASIp0, + `wasi_snapshot_preview1`, or `wasi_unstable`, it's a version of WASI. Released + in January 2024 it's the first version of WASI defined in terms of the + component model. + +* **Why does this need its own linker?** - like any target that Rust has the + `wasm32-wasip2` target needs a linker. What makes this different from other + WebAssembly targets is that WASIp2 is defined at the component level, not core + WebAssembly level. This means that filesystem functions take a `string` + instead of `i32 i32`, for example. This means that the raw output of LLVM and + `wasm-ld`, a core WebAssembly module, is not suitable. + +* **Isn't writing a linker really hard?** - Generally, yes, but this linker + works by first asking `wasm-ld` to do all the hard work. It invokes `wasm-ld` + and then uses the output core WebAssembly module to create a component. + +* **How do you create a component from a core module?** - this is the purpose of + the [`wit-component`] crate, notably the `ComponentEncoder` type. This uses + component type information embedded in the core module and a general set of + conventions/guidelines with what the core module imports/exports. A component + is then hooked up to codify all of these conventions in a component itself. + +* **Why not require users to run `wit-component` themselves?** - while possible + it adds friction to the usage `wasm32-wasip2` target. More importantly though + the "module only" output of the `wasm32-wasip2` target is not ready right now. + The standard library still imports from `wasi_snapshot_preview1` and it will + take time to migrate all usage to WASIp2. + +* **What exactly does this linker do?** - the `wasm-component-ld` has the same + CLI interface and flags as `wasm-ld`, plus some more that are + component-specific. These flags are used to forward most flags to `wasm-ld` to + produce a core wasm module. After the core wasm module is produced the + `wit-component` crate will read custom sections in the final binary which + contain component type information. After merging all this type information + together a component is produced which wraps the core module. + +If you've got any other questions about this linker or its operation don't +hesitate to reach out to the maintainers of the `wasm32-wasip2` target. + +[`wasm-component-ld`]: https://crates.io/crates/wasm-component-ld +[`wit-component`]: https://crates.io/crates/wit-component +[WebAssembly Component]: https://github.com/webassembly/component-model +[component docs]: https://component-model.bytecodealliance.org/ diff --git a/src/tools/wasm-component-ld/src/main.rs b/src/tools/wasm-component-ld/src/main.rs new file mode 100644 index 00000000000..caaac651c4c --- /dev/null +++ b/src/tools/wasm-component-ld/src/main.rs @@ -0,0 +1,9 @@ +// See the `README.md` in this directory for what this tool is. + +// The source for this crate lives at +// https://github.com/bytecodealliance/wasm-component-ld and the binary is +// independently used in other projects such as `wasi-sdk` so the `main` +// function is just reexported here to delegate. A Cargo dependency is used to +// facilitate version management in the Rust repository and work well with +// vendored/offline builds. +use wasm_component_ld::main; diff --git a/tests/run-make/raw-dylib-custom-dlltool/Makefile b/tests/run-make/raw-dylib-custom-dlltool/Makefile deleted file mode 100644 index f5d5360a3fb..00000000000 --- a/tests/run-make/raw-dylib-custom-dlltool/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Test using -Cdlltool to change where raw-dylib looks for the dlltool binary. - -# only-windows -# only-gnu -# needs-dlltool - -include ../tools.mk - -all: - $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs -Cdlltool=$(CURDIR)/script.cmd - $(DIFF) output.txt "$(TMPDIR)"/output.txt diff --git a/tests/run-make/raw-dylib-custom-dlltool/rmake.rs b/tests/run-make/raw-dylib-custom-dlltool/rmake.rs new file mode 100644 index 00000000000..86b952f0b45 --- /dev/null +++ b/tests/run-make/raw-dylib-custom-dlltool/rmake.rs @@ -0,0 +1,24 @@ +// Instead of using the default dlltool, the rust compiler can also accept a custom +// command file with the -C dlltool flag. This test uses it to compile some rust code +// with the raw_dylib Windows-exclusive feature, and checks that the output contains +// the string passed from the custom dlltool, confirming that the default dlltool was +// successfully overridden. +// See https://github.com/rust-lang/rust/pull/109677 + +//@ only-windows +//@ only-gnu +//@ needs-dlltool +// Reason: this test specifically checks the custom dlltool feature, only +// available on Windows-gnu. + +use run_make_support::{diff, rustc}; + +fn main() { + let out = rustc() + .crate_type("lib") + .crate_name("raw_dylib_test") + .input("lib.rs") + .arg("-Cdlltool=script.cmd") + .run(); + diff().expected_file("output.txt").actual_file("actual.txt").normalize(r#"\r"#, "").run(); +} diff --git a/tests/run-make/raw-dylib-custom-dlltool/script.cmd b/tests/run-make/raw-dylib-custom-dlltool/script.cmd index 95f85c61c67..51834590be0 100644 --- a/tests/run-make/raw-dylib-custom-dlltool/script.cmd +++ b/tests/run-make/raw-dylib-custom-dlltool/script.cmd @@ -1,2 +1,2 @@ -echo Called dlltool via script.cmd> %TMPDIR%\output.txt +echo Called dlltool via script.cmd> actual.txt dlltool.exe %* diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile deleted file mode 100644 index 6b44b40e253..00000000000 --- a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# Regression test for calling an inline function that uses a raw-dylib function. - -# only-windows - -include ../tools.mk - -# We'd be using the llvm-objdump instead of the system objdump to ensure compatibility -# with the LLVM bitcode generated by rustc but on Windows piping/IO redirection under MSYS2 is wonky with llvm-objdump. -OBJDUMP = objdump - -all: - $(RUSTC) --crate-type dylib --crate-name raw_dylib_test lib.rs -C prefer-dynamic - $(RUSTC) --crate-type dylib --crate-name raw_dylib_test_wrapper lib_wrapper.rs -C prefer-dynamic - $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" -C prefer-dynamic - # Make sure we don't find an import to the functions we expect to be inlined. - $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function" - $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function_calls_inline" - # Make sure we do find an import to the functions we expect to be imported. - $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -e "library_function" - $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c) - $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c) -ifdef IS_MSVC - $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib - $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib -else - $(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll - $(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll -endif - $(call RUN,driver) | tr -d '\r' > "$(TMPDIR)"/output.txt - $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/rmake.rs b/tests/run-make/raw-dylib-inline-cross-dylib/rmake.rs new file mode 100644 index 00000000000..6e3b31a0cdb --- /dev/null +++ b/tests/run-make/raw-dylib-inline-cross-dylib/rmake.rs @@ -0,0 +1,61 @@ +// When we generate the import library for a dylib or bin crate, we should generate it +// for the symbols both for the current crate and all upstream crates. This allows for +// using the link kind `raw-dylib` inside inline functions successfully. This test checks +// that the import symbols in the object files match this convention, and that execution +// of the binary results in all function names exported successfully. +// See https://github.com/rust-lang/rust/pull/102988 + +//@ only-windows + +use run_make_support::{cc, diff, is_msvc, llvm_objdump, run, rustc}; + +fn main() { + rustc() + .crate_type("dylib") + .crate_name("raw_dylib_test") + .input("lib.rs") + .arg("-Cprefer-dynamic") + .run(); + rustc() + .crate_type("dylib") + .crate_name("raw_dylib_test_wrapper") + .input("lib_wrapper.rs") + .arg("-Cprefer-dynamic") + .run(); + rustc().crate_type("bin").input("driver.rs").arg("-Cprefer-dynamic").run(); + llvm_objdump() + .arg("--private-headers") + .input("driver.exe") + .run() + // Make sure we don't find an import to the functions we expect to be inlined. + .assert_stdout_not_contains("inline_library_function") + // Make sure we do find an import to the functions we expect to be imported. + .assert_stdout_contains("library_function"); + if is_msvc() { + cc().arg("-c").out_exe("extern_1").input("extern_1.c").run(); + cc().arg("-c").out_exe("extern_2").input("extern_2.c").run(); + cc().input("extern_1.obj") + .arg("-link") + .arg("-dll") + .arg("-out:extern_1.dll") + .arg("-noimplib") + .run(); + cc().input("extern_2.obj") + .arg("-link") + .arg("-dll") + .arg("-out:extern_2.dll") + .arg("-noimplib") + .run(); + } else { + cc().arg("-v").arg("-c").out_exe("extern_1").input("extern_1.c").run(); + cc().arg("-v").arg("-c").out_exe("extern_2").input("extern_2.c").run(); + cc().input("extern_1").out_exe("extern_1.dll").arg("-shared").run(); + cc().input("extern_2").out_exe("extern_2.dll").arg("-shared").run(); + } + let out = run("driver").stdout_utf8(); + diff() + .expected_file("output.txt") + .actual_text("actual_output", out) + .normalize(r#"\r"#, "") + .run(); +} diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr index 131adfd588c..f7f3e368a3c 100644 --- a/tests/rustdoc-ui/track-diagnostics.stderr +++ b/tests/rustdoc-ui/track-diagnostics.stderr @@ -3,7 +3,7 @@ error[E0308]: mismatched types | LL | const S: A = B; | ^ expected `A`, found `B` --Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC +-Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC error: aborting due to 1 previous error diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs index f378e05304b..f15e6aa81af 100644 --- a/tests/ui/delegation/bad-resolve.rs +++ b/tests/ui/delegation/bad-resolve.rs @@ -34,6 +34,9 @@ impl Trait for S { reuse foo { &self.0 } //~^ ERROR cannot find function `foo` in this scope + reuse Trait::foo2 { self.0 } + //~^ ERROR cannot find function `foo2` in trait `Trait` + //~| ERROR method `foo2` is not a member of trait `Trait` } mod prefix {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 883ff523bcf..32d2f3b26cb 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -25,6 +25,15 @@ LL | reuse <F as Trait>::baz; | | help: there is an associated function with a similar name: `bar` | not a member of trait `Trait` +error[E0407]: method `foo2` is not a member of trait `Trait` + --> $DIR/bad-resolve.rs:37:5 + | +LL | reuse Trait::foo2 { self.0 } + | ^^^^^^^^^^^^^----^^^^^^^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo` + | not a member of trait `Trait` + error[E0423]: expected function, found associated constant `Trait::C` --> $DIR/bad-resolve.rs:24:11 | @@ -54,6 +63,15 @@ error[E0425]: cannot find function `foo` in this scope LL | reuse foo { &self.0 } | ^^^ not found in this scope +error[E0425]: cannot find function `foo2` in trait `Trait` + --> $DIR/bad-resolve.rs:37:18 + | +LL | fn foo(&self, x: i32) -> i32 { x } + | ---------------------------- similarly named associated function `foo` defined here +... +LL | reuse Trait::foo2 { self.0 } + | ^^^^ help: an associated function with a similar name exists: `foo` + error[E0046]: not all trait items implemented, missing: `Type` --> $DIR/bad-resolve.rs:22:1 | @@ -64,18 +82,18 @@ LL | impl Trait for S { | ^^^^^^^^^^^^^^^^ missing `Type` in implementation error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix` - --> $DIR/bad-resolve.rs:40:7 + --> $DIR/bad-resolve.rs:43:7 | LL | reuse unresolved_prefix::{a, b, c}; | ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix` error[E0433]: failed to resolve: `crate` in paths can only be used in start position - --> $DIR/bad-resolve.rs:41:29 + --> $DIR/bad-resolve.rs:44:29 | LL | reuse prefix::{self, super, crate}; | ^^^^^ `crate` in paths can only be used in start position -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs index fada793bd11..dd0ee2c732f 100644 --- a/tests/ui/delegation/explicit-paths-pass.rs +++ b/tests/ui/delegation/explicit-paths-pass.rs @@ -24,8 +24,8 @@ reuse to_reuse::zero_args { self } struct S(F); impl Trait for S { - reuse Trait::bar { &self.0 } - reuse Trait::description { &self.0 } + reuse Trait::bar { self.0 } + reuse Trait::description { self.0 } reuse <F as Trait>::static_method; reuse <F as Trait>::static_method2 { S::static_method(self) } } diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs index a91ca4cb931..d42e305b252 100644 --- a/tests/ui/delegation/explicit-paths.rs +++ b/tests/ui/delegation/explicit-paths.rs @@ -34,7 +34,7 @@ mod inherent_impl_assoc_fn_to_other { use crate::*; impl S { - reuse Trait::foo1 { &self.0 } + reuse Trait::foo1 { self.0 } reuse <S as Trait>::foo2; reuse to_reuse::foo3; reuse F::foo4 { &self.0 } @@ -46,7 +46,7 @@ mod trait_impl_assoc_fn_to_other { use crate::*; impl Trait for S { - reuse Trait::foo1 { &self.0 } + reuse Trait::foo1 { self.0 } reuse <F as Trait>::foo2; reuse to_reuse::foo3; //~^ ERROR method `foo3` is not a member of trait `Trait` diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr index d33c5da4377..b5afe19f878 100644 --- a/tests/ui/delegation/explicit-paths.stderr +++ b/tests/ui/delegation/explicit-paths.stderr @@ -91,10 +91,17 @@ error[E0308]: mismatched types LL | trait Trait2 : Trait { | -------------------- found this type parameter LL | reuse <F as Trait>::foo1 { self } - | ^^^^ expected `&F`, found `&Self` + | ---- ^^^^ expected `&F`, found `&Self` + | | + | arguments to this function are incorrect | = note: expected reference `&F` found reference `&Self` +note: method defined here + --> $DIR/explicit-paths.rs:5:8 + | +LL | fn foo1(&self, x: i32) -> i32 { x } + | ^^^^ ----- error[E0277]: the trait bound `S2: Trait` is not satisfied --> $DIR/explicit-paths.rs:78:16 diff --git a/tests/ui/delegation/ice-issue-122550.stderr b/tests/ui/delegation/ice-issue-122550.stderr index c92170644e7..1a01bee3e1e 100644 --- a/tests/ui/delegation/ice-issue-122550.stderr +++ b/tests/ui/delegation/ice-issue-122550.stderr @@ -4,15 +4,6 @@ error[E0308]: mismatched types LL | fn description(&self) -> &str {} | ^^ expected `&str`, found `()` -error[E0308]: mismatched types - --> $DIR/ice-issue-122550.rs:13:39 - | -LL | reuse <S as Trait>::description { &self.0 } - | ^^^^^^^ expected `&S`, found `&F` - | - = note: expected reference `&S` - found reference `&F` - error[E0277]: the trait bound `S: Trait` is not satisfied --> $DIR/ice-issue-122550.rs:13:12 | @@ -25,6 +16,22 @@ help: this trait has no implementations, consider adding one LL | trait Trait { | ^^^^^^^^^^^ +error[E0308]: mismatched types + --> $DIR/ice-issue-122550.rs:13:39 + | +LL | reuse <S as Trait>::description { &self.0 } + | ----------- ^^^^^^^ expected `&S`, found `&F` + | | + | arguments to this function are incorrect + | + = note: expected reference `&S` + found reference `&F` +note: method defined here + --> $DIR/ice-issue-122550.rs:5:8 + | +LL | fn description(&self) -> &str {} + | ^^^^^^^^^^^ ----- + error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/tests/ui/delegation/method-call-choice.rs b/tests/ui/delegation/method-call-choice.rs new file mode 100644 index 00000000000..8d53d8bfdb7 --- /dev/null +++ b/tests/ui/delegation/method-call-choice.rs @@ -0,0 +1,25 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self) {} +} + +struct F; +impl Trait for F {} +struct S(F); + +pub mod to_reuse { + use crate::F; + + pub fn foo(_: &F) {} +} + +impl Trait for S { + // Make sure that the method call is not generated if the path resolution + // does not have a `self` parameter. + reuse to_reuse::foo { self.0 } + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/delegation/method-call-choice.stderr b/tests/ui/delegation/method-call-choice.stderr new file mode 100644 index 00000000000..6757af20a6b --- /dev/null +++ b/tests/ui/delegation/method-call-choice.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/method-call-choice.rs:21:27 + | +LL | reuse to_reuse::foo { self.0 } + | --- ^^^^^^ expected `&F`, found `F` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/method-call-choice.rs:15:12 + | +LL | pub fn foo(_: &F) {} + | ^^^ ----- +help: consider borrowing here + | +LL | reuse to_reuse::foo { &self.0 } + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/delegation/method-call-priority.rs b/tests/ui/delegation/method-call-priority.rs new file mode 100644 index 00000000000..8d68740d181 --- /dev/null +++ b/tests/ui/delegation/method-call-priority.rs @@ -0,0 +1,34 @@ +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(dead_code)] + +trait Trait1 { + fn foo(&self) -> i32 { 1 } +} + +trait Trait2 { + fn foo(&self) -> i32 { 2 } +} + +struct F; +impl Trait1 for F {} +impl Trait2 for F {} + +impl F { + fn foo(&self) -> i32 { 3 } +} + +struct S(F); + +impl Trait1 for S { + // Make sure that the generated `self.0.foo()` does not turn into the inherent method `F::foo` + // that has a higher priority than methods from traits. + reuse Trait1::foo { self.0 } +} + +fn main() { + let s = S(F); + assert_eq!(s.foo(), 1); +} diff --git a/tests/ui/delegation/self-coercion.rs b/tests/ui/delegation/self-coercion.rs new file mode 100644 index 00000000000..96c1f1b140b --- /dev/null +++ b/tests/ui/delegation/self-coercion.rs @@ -0,0 +1,26 @@ +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait : Sized { + fn by_value(self) -> i32 { 1 } + fn by_mut_ref(&mut self) -> i32 { 2 } + fn by_ref(&self) -> i32 { 3 } +} + +struct F; +impl Trait for F {} + +struct S(F); + +impl Trait for S { + reuse Trait::{by_value, by_mut_ref, by_ref} { self.0 } +} + +fn main() { + let mut s = S(F); + assert_eq!(s.by_ref(), 3); + assert_eq!(s.by_mut_ref(), 2); + assert_eq!(s.by_value(), 1); +} diff --git a/tests/ui/parser/cfg-keyword-lifetime.rs b/tests/ui/parser/cfg-keyword-lifetime.rs new file mode 100644 index 00000000000..a1588eddc07 --- /dev/null +++ b/tests/ui/parser/cfg-keyword-lifetime.rs @@ -0,0 +1,15 @@ +// Disallow `'keyword` even in cfg'd code. + +#[cfg(any())] +fn hello() -> &'ref () {} +//~^ ERROR lifetimes cannot use keyword names + +macro_rules! macro_invocation { + ($i:item) => {} +} +macro_invocation! { + fn hello() -> &'ref () {} + //~^ ERROR lifetimes cannot use keyword names +} + +fn main() {} diff --git a/tests/ui/parser/cfg-keyword-lifetime.stderr b/tests/ui/parser/cfg-keyword-lifetime.stderr new file mode 100644 index 00000000000..52d305e2521 --- /dev/null +++ b/tests/ui/parser/cfg-keyword-lifetime.stderr @@ -0,0 +1,14 @@ +error: lifetimes cannot use keyword names + --> $DIR/cfg-keyword-lifetime.rs:4:16 + | +LL | fn hello() -> &'ref () {} + | ^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/cfg-keyword-lifetime.rs:11:20 + | +LL | fn hello() -> &'ref () {} + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/require-parens-for-chained-comparison.rs b/tests/ui/parser/require-parens-for-chained-comparison.rs index 5b90e905a64..916f1b83db2 100644 --- a/tests/ui/parser/require-parens-for-chained-comparison.rs +++ b/tests/ui/parser/require-parens-for-chained-comparison.rs @@ -24,12 +24,14 @@ fn main() { //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments //~| ERROR expected //~| HELP add `'` to close the char literal + //~| ERROR invalid label name f<'_>(); //~^ comparison operators cannot be chained //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments //~| ERROR expected //~| HELP add `'` to close the char literal + //~| ERROR invalid label name let _ = f<u8>; //~^ ERROR comparison operators cannot be chained diff --git a/tests/ui/parser/require-parens-for-chained-comparison.stderr b/tests/ui/parser/require-parens-for-chained-comparison.stderr index 52e201c435c..857c4a55788 100644 --- a/tests/ui/parser/require-parens-for-chained-comparison.stderr +++ b/tests/ui/parser/require-parens-for-chained-comparison.stderr @@ -53,6 +53,12 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::<u8, i8>(); | ++ +error: invalid label name `'_` + --> $DIR/require-parens-for-chained-comparison.rs:22:15 + | +LL | let _ = f<'_, i8>(); + | ^^ + error: expected `while`, `for`, `loop` or `{` after a label --> $DIR/require-parens-for-chained-comparison.rs:22:17 | @@ -75,8 +81,14 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::<'_, i8>(); | ++ +error: invalid label name `'_` + --> $DIR/require-parens-for-chained-comparison.rs:29:7 + | +LL | f<'_>(); + | ^^ + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/require-parens-for-chained-comparison.rs:28:9 + --> $DIR/require-parens-for-chained-comparison.rs:29:9 | LL | f<'_>(); | ^ expected `while`, `for`, `loop` or `{` after a label @@ -87,7 +99,7 @@ LL | f<'_'>(); | + error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:28:6 + --> $DIR/require-parens-for-chained-comparison.rs:29:6 | LL | f<'_>(); | ^ ^ @@ -98,7 +110,7 @@ LL | f::<'_>(); | ++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:34:14 + --> $DIR/require-parens-for-chained-comparison.rs:36:14 | LL | let _ = f<u8>; | ^ ^ @@ -106,5 +118,5 @@ LL | let _ = f<u8>; = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index 8298293a8cb..f9cde810cad 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -4,6 +4,12 @@ error: expected identifier, found keyword `Self` LL | struct Self; | ^^^^ expected identifier, found keyword +error: lifetimes cannot use keyword names + --> $DIR/self_type_keyword.rs:6:12 + | +LL | struct Bar<'Self>; + | ^^^^^ + error: expected identifier, found keyword `Self` --> $DIR/self_type_keyword.rs:14:13 | @@ -53,12 +59,6 @@ error: expected identifier, found keyword `Self` LL | trait Self {} | ^^^^ expected identifier, found keyword -error: lifetimes cannot use keyword names - --> $DIR/self_type_keyword.rs:6:12 - | -LL | struct Bar<'Self>; - | ^^^^^ - error: cannot find macro `Self` in this scope --> $DIR/self_type_keyword.rs:21:9 | |
