diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f87aecb68769..398a70ee6a23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: env: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" CACHE_DOMAIN: ci-caches.rust-lang.org @@ -143,6 +144,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: @@ -156,6 +168,7 @@ jobs: env: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" @@ -557,6 +570,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: @@ -571,6 +595,7 @@ jobs: DIST_TRY_BUILD: 1 CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" @@ -672,6 +697,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index bad87db47323..b62f4676f70b 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -108,6 +108,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.const_uint(self.type_u64(), i) } + fn const_u128(&self, i: u128) -> RValue<'gcc> { + self.const_uint_big(self.type_u128(), i) + } + fn const_usize(&self, i: u64) -> RValue<'gcc> { let bit_size = self.data_layout().pointer_size.bits(); if bit_size < 64 { @@ -254,7 +258,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // SIMD builtins require a constant value. self.bitcast_if_needed(value, typ) } - + fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None) } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a3910fef9549..a2db59bd6c47 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -168,6 +168,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.const_uint(self.type_i64(), i) } + fn const_u128(&self, i: u128) -> &'ll Value { + self.const_uint_big(self.type_i128(), i) + } + fn const_usize(&self, i: u64) -> &'ll Value { let bit_size = self.data_layout().pointer_size.bits(); if bit_size < 64 { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index fa67a1b33101..1a8618e0c557 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -429,7 +429,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D return existing_di_node; } - debug!("type_di_node: {:?}", t); + debug!("type_di_node: {:?} kind: {:?}", t, t.kind()); let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 978141917c6b..666b9762f5a7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -412,13 +412,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( enum_type_and_layout.size.bits(), enum_type_and_layout.align.abi.bits() as u32, Size::ZERO.bits(), - discr_value.opt_single_val().map(|value| { - // NOTE(eddyb) do *NOT* remove this assert, until - // we pass the full 128-bit value to LLVM, otherwise - // truncation will be silent and remain undetected. - assert_eq!(value as u64 as u128, value); - cx.const_u64(value as u64) - }), + discr_value.opt_single_val().map(|value| cx.const_u128(value)), DIFlags::FlagZero, variant_member_info.variant_struct_type_di_node, ) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8d346c8c0d0d..557b120b2c8f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorGuaranteed, Handler}; -use rustc_fs_util::fix_windows_verbatim_for_gcc; +use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; @@ -2682,6 +2682,30 @@ fn add_upstream_native_libraries( } } +// Rehome lib paths (which exclude the library file name) that point into the sysroot lib directory +// to be relative to the sysroot directory, which may be a relative path specified by the user. +// +// If the sysroot is a relative path, and the sysroot libs are specified as an absolute path, the +// linker command line can be non-deterministic due to the paths including the current working +// directory. The linker command line needs to be deterministic since it appears inside the PDB +// file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586. +// +// The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it. +fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { + let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); + let canonical_sysroot_lib_path = + { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; + + let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf()); + if canonical_lib_dir == canonical_sysroot_lib_path { + // This path, returned by `target_filesearch().get_lib_path()`, has + // already had `fix_windows_verbatim_for_gcc()` applied if needed. + sysroot_lib_path + } else { + fix_windows_verbatim_for_gcc(&lib_dir) + } +} + // Adds the static "rlib" versions of all crates to the command line. // There's a bit of magic which happens here specifically related to LTO, // namely that we remove upstream object files. @@ -2713,7 +2737,13 @@ fn add_static_crate<'a>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - cmd.link_rlib(&fix_windows_verbatim_for_gcc(path)); + let rlib_path = if let Some(dir) = path.parent() { + let file_name = path.file_name().expect("rlib path has no file name path component"); + rehome_sysroot_lib_dir(sess, &dir).join(file_name) + } else { + fix_windows_verbatim_for_gcc(path) + }; + cmd.link_rlib(&rlib_path); }; if !are_upstream_rust_objects_already_included(sess) @@ -2782,7 +2812,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { // what its name is let parent = cratepath.parent(); if let Some(dir) = parent { - cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); + cmd.include_path(&rehome_sysroot_lib_dir(sess, dir)); } let stem = cratepath.file_stem().unwrap().to_str().unwrap(); // Convert library file-stem into a cc -l argument. diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index dc2fc3964801..d6e9bfce1a4f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -15,6 +15,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_i32(&self, i: i32) -> Self::Value; fn const_u32(&self, i: u32) -> Self::Value; fn const_u64(&self, i: u64) -> Self::Value; + fn const_u128(&self, i: u128) -> Self::Value; fn const_usize(&self, i: u64) -> Self::Value; fn const_u8(&self, i: u8) -> Self::Value; fn const_real(&self, t: Self::Type, val: f64) -> Self::Value; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 57d939747aab..106cf1114749 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -781,8 +781,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); return; } - Ok(Some(ImplSource::Closure(data))) => { - if !tcx.is_const_fn_raw(data.closure_def_id) { + // Closure: Fn{Once|Mut} + Ok(Some(ImplSource::Builtin(_))) + if poly_trait_pred.self_ty().skip_binder().is_closure() + && tcx.fn_trait_kind_from_def_id(trait_id).is_some() => + { + let ty::Closure(closure_def_id, substs) = + *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind() + else { + unreachable!() + }; + if !tcx.is_const_fn_raw(closure_def_id) { self.check_op(ops::FnCallNonConst { caller, callee, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1da20579021a..a2d23425f3bc 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -172,7 +172,7 @@ impl Qualif for NeedsNonConstDrop { if !matches!( impl_src, - ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) ) { // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 11ad5b49df2e..4f01e0a24a5d 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -63,6 +63,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), + ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"), ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"), ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"), diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index b2bdf9c7e6db..40bfa3715be7 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -9,7 +9,7 @@ use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::edition::Edition; -use rustc_span::{Span, SyntaxContext}; +use rustc_span::Span; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ @@ -72,7 +72,7 @@ pub(super) fn parse( // `SyntaxContext::root()` from a foreign crate will // have the edition of that crate (which we manually // retrieve via the `edition` parameter). - if span.ctxt() == SyntaxContext::root() { + if span.ctxt().is_root() { edition } else { span.edition() diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 4b3bc816b953..4e23a28b3716 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -260,6 +260,8 @@ language_item_table! { EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1); + // Experimental language item for Miri + PtrUnique, sym::ptr_unique, ptr_unique, Target::Struct, GenericRequirement::Exact(1); PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1); diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs new file mode 100644 index 000000000000..05a3ab63d5cf --- /dev/null +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -0,0 +1,124 @@ +use rustc_ast::TraitObjectSyntax; +use rustc_errors::{Diagnostic, StashKey}; +use rustc_hir as hir; +use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; +use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; + +use super::AstConv; + +impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + /// Make sure that we are in the condition to suggest the blanket implementation. + pub(super) fn maybe_lint_blanket_trait_impl( + &self, + self_ty: &hir::Ty<'_>, + diag: &mut Diagnostic, + ) { + let tcx = self.tcx(); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + if let hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Impl(hir::Impl { + self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. + }), + .. + }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id + { + if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { + return; + } + let of_trait_span = of_trait_ref.path.span; + // make sure that we are not calling unwrap to abort during the compilation + let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {}: {}", param_name, impl_trait_name)) + } else { + (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) + }; + diag.multipart_suggestion( + format!("alternatively use a blanket \ + implementation to implement `{of_trait_name}` for \ + all types that also implement `{impl_trait_name}`"), + vec![ + (self_ty.span, param_name), + add_generic_sugg, + ], + Applicability::MaybeIncorrect, + ); + } + } + + pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { + let tcx = self.tcx(); + if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + { + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(self_ty.span) + .ok() + .is_some_and(|s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + + let mut sugg = Vec::from_iter([( + self_ty.span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + )]); + + if is_global || needs_bracket { + sugg.push(( + self_ty.span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + )); + } + + if self_ty.span.edition().rust_2021() { + let msg = "trait objects must include the `dyn` keyword"; + let label = "add `dyn` keyword before this trait"; + let mut diag = + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); + if self_ty.span.can_be_used_for_suggestions() { + diag.multipart_suggestion_verbose( + label, + sugg, + Applicability::MachineApplicable, + ); + } + // check if the impl trait that we are considering is a impl of a local trait + self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + diag.stash(self_ty.span, StashKey::TraitMissingMethod); + } else { + let msg = "trait objects without an explicit `dyn` are deprecated"; + tcx.struct_span_lint_hir( + BARE_TRAIT_OBJECTS, + self_ty.hir_id, + self_ty.span, + msg, + |lint| { + lint.multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + self.maybe_lint_blanket_trait_impl(&self_ty, lint); + lint + }, + ); + } + } + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1037a49acdf3..221c7ce4f6ff 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -4,6 +4,7 @@ mod errors; pub mod generics; +mod lint; use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args}; @@ -19,7 +20,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError, - MultiSpan, StashKey, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; @@ -33,14 +34,12 @@ use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{DynKind, ToPredicate}; -use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; +use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_target::spec::abi; -use rustc_trait_selection::traits::error_reporting::{ - report_object_safety_error, suggestions::NextTypeParamName, -}; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{ self, astconv_object_safety_violations, NormalizeExt, ObligationCtxt, @@ -1458,7 +1457,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment<'_>, ) -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.tcx().at(span).type_of(did).subst(self.tcx(), substs) + let ty = self.tcx().at(span).type_of(did); + + if matches!(self.tcx().def_kind(did), DefKind::TyAlias) + && ty.skip_binder().has_opaque_types() + { + // Type aliases referring to types that contain opaque types (but aren't just directly + // referencing a single opaque type) get encoded as a type alias that normalization will + // then actually instantiate the where bounds of. + let alias_ty = self.tcx().mk_alias_ty(did, substs); + self.tcx().mk_alias(ty::Weak, alias_ty) + } else { + ty.subst(self.tcx(), substs) + } } fn conv_object_ty_poly_trait_ref( @@ -3703,115 +3714,4 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Some(r) } - - /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { - let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - if let hir::Node::Item(hir::Item { - kind: - hir::ItemKind::Impl(hir::Impl { - self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. - }), - .. - }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id - { - if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { - return; - } - let of_trait_span = of_trait_ref.path.span; - // make sure that we are not calling unwrap to abort during the compilation - let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; - let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; - // check if the trait has generics, to make a correct suggestion - let param_name = generics.params.next_type_param_name(None); - - let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { - (span, format!(", {}: {}", param_name, impl_trait_name)) - } else { - (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) - }; - diag.multipart_suggestion( - format!("alternatively use a blanket \ - implementation to implement `{of_trait_name}` for \ - all types that also implement `{impl_trait_name}`"), - vec![ - (self_ty.span, param_name), - add_generic_sugg, - ], - Applicability::MaybeIncorrect, - ); - } - } - - fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { - let tcx = self.tcx(); - if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let needs_bracket = in_path - && !tcx - .sess - .source_map() - .span_to_prev_source(self_ty.span) - .ok() - .is_some_and(|s| s.trim_end().ends_with('<')); - - let is_global = poly_trait_ref.trait_ref.path.is_global(); - - let mut sugg = Vec::from_iter([( - self_ty.span.shrink_to_lo(), - format!( - "{}dyn {}", - if needs_bracket { "<" } else { "" }, - if is_global { "(" } else { "" }, - ), - )]); - - if is_global || needs_bracket { - sugg.push(( - self_ty.span.shrink_to_hi(), - format!( - "{}{}", - if is_global { ")" } else { "" }, - if needs_bracket { ">" } else { "" }, - ), - )); - } - - if self_ty.span.edition().rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut diag = - rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() { - diag.multipart_suggestion_verbose( - label, - sugg, - Applicability::MachineApplicable, - ); - } - // check if the impl trait that we are considering is a impl of a local trait - self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); - } else { - let msg = "trait objects without an explicit `dyn` are deprecated"; - tcx.struct_span_lint_hir( - BARE_TRAIT_OBJECTS, - self_ty.hir_id, - self_ty.span, - msg, - |lint| { - lint.multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ); - self.maybe_lint_blanket_trait_impl(&self_ty, lint); - lint - }, - ); - } - } - } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4554d167080b..f93f395caed6 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -217,10 +217,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { check_item_fn(tcx, def_id, item.ident, item.span, sig.decl); } hir::ItemKind::Static(ty, ..) => { - check_item_type(tcx, def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid); } hir::ItemKind::Const(ty, ..) => { - check_item_type(tcx, def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid); } hir::ItemKind::Struct(_, ast_generics) => { check_type_defn(tcx, item, false); @@ -242,6 +242,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::TyAlias(hir_ty, ..) => { + if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { + // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` + check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); + } + } _ => {} } } @@ -258,7 +264,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { hir::ForeignItemKind::Fn(decl, ..) => { check_item_fn(tcx, def_id, item.ident, item.span, decl) } - hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true), + hir::ForeignItemKind::Static(ty, ..) => { + check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail) + } hir::ForeignItemKind::Type => (), } } @@ -1100,20 +1108,32 @@ fn check_item_fn( }) } -fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) { +enum UnsizedHandling { + Forbid, + Allow, + AllowIfForeignTail, +} + +fn check_item_type( + tcx: TyCtxt<'_>, + item_id: LocalDefId, + ty_span: Span, + unsized_handling: UnsizedHandling, +) { debug!("check_item_type: {:?}", item_id); enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| { let ty = tcx.type_of(item_id).subst_identity(); let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty); - let mut forbid_unsized = true; - if allow_foreign_ty { - let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); - if let ty::Foreign(_) = tail.kind() { - forbid_unsized = false; + let forbid_unsized = match unsized_handling { + UnsizedHandling::Forbid => true, + UnsizedHandling::Allow => false, + UnsizedHandling::AllowIfForeignTail => { + let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); + !matches!(tail.kind(), ty::Foreign(_)) } - } + }; wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); if forbid_unsized { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 23beacd2a8c2..eb299a1ea799 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -200,35 +200,32 @@ fn do_orphan_check_impl<'tcx>( NonlocalImpl::DisallowOther, ), - // trait Id { type This: ?Sized; } - // impl Id for T { - // type This = T; - // } - // impl AutoTrait for ::This {} - ty::Alias(AliasKind::Projection, _) => ( - LocalImpl::Disallow { problematic_kind: "associated type" }, - NonlocalImpl::DisallowOther, - ), - - // ``` - // struct S(T); - // impl S { - // type This = T; - // } - // impl AutoTrait for S::This {} - // ``` - // FIXME(inherent_associated_types): The example code above currently leads to a cycle - ty::Alias(AliasKind::Inherent, _) => ( - LocalImpl::Disallow { problematic_kind: "associated type" }, - NonlocalImpl::DisallowOther, - ), - - // type Opaque = impl Trait; - // impl AutoTrait for Opaque {} - ty::Alias(AliasKind::Opaque, _) => ( - LocalImpl::Disallow { problematic_kind: "opaque type" }, - NonlocalImpl::DisallowOther, - ), + ty::Alias(kind, _) => { + let problematic_kind = match kind { + // trait Id { type This: ?Sized; } + // impl Id for T { + // type This = T; + // } + // impl AutoTrait for ::This {} + AliasKind::Projection => "associated type", + // type Foo = (impl Sized, bool) + // impl AutoTrait for Foo {} + AliasKind::Weak => "type alias", + // type Opaque = impl Trait; + // impl AutoTrait for Opaque {} + AliasKind::Opaque => "opaque type", + // ``` + // struct S(T); + // impl S { + // type This = T; + // } + // impl AutoTrait for S::This {} + // ``` + // FIXME(inherent_associated_types): The example code above currently leads to a cycle + AliasKind::Inherent => "associated type", + }; + (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) + } ty::Bool | ty::Char diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index b92d561fb86a..90e8e523ea3e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -122,6 +122,7 @@ pub(super) fn explicit_item_bounds( }; opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } + hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[], _ => bug!("item_bounds called on {:?}", def_id), }; ty::EarlyBinder::bind(bounds) diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index e4c6e6e391a1..a653a6522313 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>( ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { - hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty], + hir::ItemKind::TyAlias(ty, _) + | hir::ItemKind::Static(ty, _, _) + | hir::ItemKind::Const(ty, _) => vec![ty], hir::ItemKind::Impl(impl_) => match &impl_.of_trait { Some(t) => t .path diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 9659a0ec13d4..dce426ca2db6 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); - let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: self.tcx.def_span(expr_def_id), }); @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a type variable (for now) to represent the closure kind. // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_ty_var(TypeVariableOrigin { + None => self.next_root_ty_var(TypeVariableOrigin { // FIXME(eddyb) distinguish closure kind inference variables from the rest. kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 67f45f9aa3f0..630878bbf0c6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.tcx.sess.err_count() > self.err_count_on_creation } + + pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { + self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) + } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3e4812e7ca99..fc1f90fdc13f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2375,6 +2375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::AliasKind::Projection | ty::AliasKind::Inherent => { format!("the associated type `{}`", p) } + ty::AliasKind::Weak => format!("the type alias `{}`", p), ty::AliasKind::Opaque => format!("the opaque type `{}`", p), }, }; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7b05bff51514..f02f3668dc1f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1465,8 +1465,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { return }; - if let hir::TyKind::OpaqueDef(..) = ty.kind { - // Bounds are respected for `type X = impl Trait` + if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { + // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` return; } if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index ec9e7c7fdae8..9a2d45ccd663 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1255,7 +1255,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } ty::Param(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Infer(..) | ty::Bound(..) | ty::Error(_) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 29dae67bfca7..1b19ed9ad148 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> { } pub fn is_identity_modulo_regions(&self) -> bool { - self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { - ty::GenericArgKind::Lifetime(_) => true, - ty::GenericArgKind::Type(ty) => { - matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) + let mut var = ty::BoundVar::from_u32(0); + for arg in self.var_values { + match arg.unpack() { + ty::GenericArgKind::Lifetime(r) => { + if let ty::ReLateBound(ty::INNERMOST, br) = *r + && var == br.var + { + var = var + 1; + } else { + // It's ok if this region var isn't unique + } + }, + ty::GenericArgKind::Type(ty) => { + if let ty::Bound(ty::INNERMOST, bt) = *ty.kind() + && var == bt.var + { + var = var + 1; + } else { + return false; + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind() + && var == bc + { + var = var + 1; + } else { + return false; + } + } } - ty::GenericArgKind::Const(ct) => { - matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) - } - }) + } + + true } } diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 2165403da267..6b0361943818 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -3,7 +3,7 @@ use rustc_middle::hir; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_session::config::MirSpanview; -use rustc_span::{BytePos, Pos, Span, SyntaxContext}; +use rustc_span::{BytePos, Pos, Span}; use std::cmp; use std::io::{self, Write}; @@ -327,7 +327,7 @@ fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span { let mut span = data.terminator().source_info.span; for statement_span in data.statements.iter().map(|statement| statement.source_info.span) { // Only combine Spans from the root context, and within the function's body_span. - if statement_span.ctxt() == SyntaxContext::root() && body_span.contains(statement_span) { + if statement_span.ctxt().is_root() && body_span.contains(statement_span) { span = span.to(statement_span); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a6c8d41e925f..132b11b29eb3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1903,6 +1903,16 @@ rustc_queries! { desc { "normalizing `{}`", goal.value.value } } + /// Do not call this query directly: invoke `normalize` instead. + query normalize_weak_ty( + goal: CanonicalProjectionGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.value.value } + } + /// Do not call this query directly: invoke `normalize` instead. query normalize_inherent_projection_ty( goal: CanonicalProjectionGoal<'tcx> diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index bf3872e81d4a..492b7228488f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -448,6 +448,9 @@ pub enum ObligationCauseCode<'tcx> { /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), + + /// Obligations emitted during the normalization of a weak type alias. + TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), } /// The 'location' at which we try to perform HIR-based wf checking. @@ -643,12 +646,6 @@ pub enum ImplSource<'tcx, N> { /// ImplSource identifying a particular impl. UserDefined(ImplSourceUserDefinedData<'tcx, N>), - /// ImplSource for auto trait implementations. - /// This carries the information and nested obligations with regards - /// to an auto implementation for a trait `Trait`. The nested obligations - /// ensure the trait implementation holds for all the constituent types. - AutoImpl(ImplSourceAutoImplData), - /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if @@ -656,84 +653,46 @@ pub enum ImplSource<'tcx, N> { Param(Vec, ty::BoundConstness), /// Virtual calls through an object. - Object(ImplSourceObjectData<'tcx, N>), + Object(ImplSourceObjectData), /// Successful resolution for a builtin trait. - Builtin(ImplSourceBuiltinData), + Builtin(Vec), /// ImplSource for trait upcasting coercion - TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>), - - /// ImplSource automatically generated for a closure. The `DefId` is the ID - /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the - /// impl is generated by the compiler and does not appear in the source. - Closure(ImplSourceClosureData<'tcx, N>), - - /// Same as above, but for a function pointer type with the given signature. - FnPointer(ImplSourceFnPointerData<'tcx, N>), - - /// ImplSource automatically generated for a generator. - Generator(ImplSourceGeneratorData<'tcx, N>), - - /// ImplSource automatically generated for a generator backing an async future. - Future(ImplSourceFutureData<'tcx, N>), + TraitUpcasting(ImplSourceTraitUpcastingData), /// ImplSource for a trait alias. TraitAlias(ImplSourceTraitAliasData<'tcx, N>), - - /// ImplSource for a `const Drop` implementation. - ConstDestruct(ImplSourceConstDestructData), } impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => i.nested, - ImplSource::AutoImpl(d) => d.nested, - ImplSource::Closure(c) => c.nested, - ImplSource::Generator(c) => c.nested, - ImplSource::Future(c) => c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => d.nested, - ImplSource::FnPointer(d) => d.nested, ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, - ImplSource::ConstDestruct(i) => i.nested, } } pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &i.nested, - ImplSource::AutoImpl(d) => &d.nested, - ImplSource::Closure(c) => &c.nested, - ImplSource::Generator(c) => &c.nested, - ImplSource::Future(c) => &c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n, ImplSource::Object(d) => &d.nested, - ImplSource::FnPointer(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, - ImplSource::ConstDestruct(i) => &i.nested, } } pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &mut i.nested, - ImplSource::AutoImpl(d) => &mut d.nested, - ImplSource::Closure(c) => &mut c.nested, - ImplSource::Generator(c) => &mut c.nested, - ImplSource::Future(c) => &mut c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => &mut d.nested, - ImplSource::FnPointer(d) => &mut d.nested, ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested, - ImplSource::ConstDestruct(i) => &mut i.nested, } } @@ -748,37 +707,12 @@ impl<'tcx, N> ImplSource<'tcx, N> { nested: i.nested.into_iter().map(f).collect(), }), ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), - ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData { - nested: i.nested.into_iter().map(f).collect(), - }), + ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { - upcast_trait_ref: o.upcast_trait_ref, + upcast_trait_def_id: o.upcast_trait_def_id, vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), - ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData { - trait_def_id: d.trait_def_id, - nested: d.nested.into_iter().map(f).collect(), - }), - ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData { - closure_def_id: c.closure_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData { - fn_ty: p.fn_ty, - nested: p.nested.into_iter().map(f).collect(), - }), ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { alias_def_id: d.alias_def_id, substs: d.substs, @@ -786,16 +720,10 @@ impl<'tcx, N> ImplSource<'tcx, N> { }), ImplSource::TraitUpcasting(d) => { ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { - upcast_trait_ref: d.upcast_trait_ref, vtable_vptr_slot: d.vtable_vptr_slot, nested: d.nested.into_iter().map(f).collect(), }) } - ImplSource::ConstDestruct(i) => { - ImplSource::ConstDestruct(ImplSourceConstDestructData { - nested: i.nested.into_iter().map(f).collect(), - }) - } } } } @@ -820,47 +748,7 @@ pub struct ImplSourceUserDefinedData<'tcx, N> { #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceGeneratorData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFutureData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceClosureData<'tcx, N> { - pub closure_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the closure - /// signature contains associated types. - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceAutoImplData { - pub trait_def_id: DefId, - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitUpcastingData<'tcx, N> { - /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, - +pub struct ImplSourceTraitUpcastingData { /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable @@ -870,17 +758,11 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceBuiltinData { - pub nested: Vec, -} - #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceObjectData<'tcx, N> { +pub struct ImplSourceObjectData { /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, + pub upcast_trait_def_id: DefId, /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will @@ -891,19 +773,6 @@ pub struct ImplSourceObjectData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFnPointerData<'tcx, N> { - pub fn_ty: Ty<'tcx>, - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceConstDestructData { - pub nested: Vec, -} - #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitAliasData<'tcx, N> { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 6acb7745d654..ac02d6ed62f2 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -9,15 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { match *self { super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), - super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t), - - super::ImplSource::Closure(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Generator(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Future(ref d) => write!(f, "{:?}", d), - - super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d), + super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), super::ImplSource::Object(ref d) => write!(f, "{:?}", d), @@ -25,13 +17,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) } - super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), - super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), - - super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d), } } } @@ -46,78 +34,26 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx, } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N> { +impl fmt::Debug for traits::ImplSourceTraitUpcastingData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested + "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})", + self.vtable_vptr_slot, self.nested ) } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceClosureData(closure_def_id={:?}, substs={:?}, nested={:?})", - self.closure_def_id, self.substs, self.nested - ) - } -} - -impl fmt::Debug for traits::ImplSourceBuiltinData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceBuiltinData(nested={:?})", self.nested) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceTraitUpcastingData(upcast={:?}, vtable_vptr_slot={:?}, nested={:?})", - self.upcast_trait_ref, self.vtable_vptr_slot, self.nested - ) - } -} - -impl fmt::Debug for traits::ImplSourceAutoImplData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceAutoImplData(trait_def_id={:?}, nested={:?})", - self.trait_def_id, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> { +impl fmt::Debug for traits::ImplSourceObjectData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "ImplSourceObjectData(upcast={:?}, vtable_base={}, nested={:?})", - self.upcast_trait_ref, self.vtable_base, self.nested + self.upcast_trait_def_id, self.vtable_base, self.nested ) } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFnPointerData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested) - } -} - impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -127,9 +63,3 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, ) } } - -impl fmt::Debug for traits::ImplSourceConstDestructData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested) - } -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4ee543bbfb6d..449129b84188 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2012,6 +2012,7 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + | (ty::Weak, DefKind::TyAlias) ); self.mk_ty_from_kind(Alias(kind, alias_ty)) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 66293f19eef6..c794c3faded1 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -300,6 +300,7 @@ impl<'tcx> Ty<'tcx> { ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(), + ty::Alias(ty::Weak, _) => "type alias".into(), ty::Param(_) => "type parameter".into(), ty::Alias(ty::Opaque, ..) => "opaque type".into(), } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index d64875a9f00e..9cce9d64d5d2 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -178,7 +178,7 @@ impl FlagComputation { &ty::Alias(kind, data) => { self.add_flags(match kind { - ty::Projection => TypeFlags::HAS_TY_PROJECTION, + ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION, ty::Inherent => TypeFlags::HAS_TY_INHERENT, ty::Opaque => TypeFlags::HAS_TY_OPAQUE, }); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72341e656e29..ff5d99794f1e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -586,6 +586,24 @@ pub enum Clause<'tcx> { ConstArgHasType(Const<'tcx>, Ty<'tcx>), } +impl<'tcx> Binder<'tcx, Clause<'tcx>> { + pub fn as_trait_clause(self) -> Option>> { + if let ty::Clause::Trait(trait_clause) = self.skip_binder() { + Some(self.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option>> { + if let ty::Clause::Projection(projection_clause) = self.skip_binder() { + Some(self.rebind(projection_clause)) + } else { + None + } + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub enum PredicateKind<'tcx> { @@ -1203,6 +1221,17 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + Binder::dummy(Clause::Trait(TraitPredicate { + trait_ref: self, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + })) + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1211,6 +1240,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { @@ -1240,6 +1277,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Trait(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) @@ -1258,6 +1301,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Projection(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) @@ -1327,6 +1376,23 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeWellFormedFromEnv(..) => None, } } + + pub fn as_clause(self) -> Option>> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(clause) => Some(predicate.rebind(clause)), + PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } } /// Represents the bounds declared on a particular set of type diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6156fdf7eac2..f36b8ad8df6c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -731,7 +731,7 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Alias(ty::Projection | ty::Inherent, ref data) => { + ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => { if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get())) && self.tcx().is_impl_trait_in_trait(data.def_id) { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8bcae3d9ab7c..74a3bddf2fae 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -391,13 +391,13 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { /// Relates `a` and `b` structurally, calling the relation for all nested values. /// Any semantic equality, e.g. of projections, and inference variables have to be /// handled by the caller. +#[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { let tcx = relation.tcx(); - debug!("structurally_relate_tys: a={:?} b={:?}", a, b); match (a.kind(), b.kind()) { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { // The caller should handle these cases! diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d19a7bcde79b..5f2f241bc0dc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1231,6 +1231,7 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index ef64f70fdf34..fd349c07040f 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -15,6 +15,10 @@ pub struct CheckAlignment; impl<'tcx> MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { + // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows + if sess.target.llvm_target == "i686-pc-windows-msvc" { + return false; + } sess.opts.debug_assertions } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 5487b5987e00..b28fed7159f1 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -479,11 +479,12 @@ impl<'tcx> Inliner<'tcx> { // Abort if type validation found anything fishy. checker.validation?; + // N.B. We still apply our cost threshold to #[inline(always)] functions. + // That attribute is often applied to very large functions that exceed LLVM's (very + // generous) inlining threshold. Such functions are very poor MIR inlining candidates. + // Always inlining #[inline(always)] functions in MIR, on net, slows down the compiler. let cost = checker.cost; - if let InlineAttr::Always = callee_attrs.inline { - debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost); - Ok(()) - } else if cost <= threshold { + if cost <= threshold { debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold); Ok(()) } else { diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index ebcc3b039997..531644f0b849 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -155,15 +155,17 @@ where // functions and statics defined in the local crate. let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - place_root_mono_items(cx, mono_items) + let mut placed = place_root_mono_items(cx, mono_items); + + for cgu in &mut placed.codegen_units { + cgu.create_size_estimate(tcx); + } + + debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats); + + placed }; - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); - } - - debug_dump(tcx, "ROOTS", &codegen_units, unique_inlined_stats); - // Merge until we have at most `max_cgu_count` codegen units. // `merge_codegen_units` is responsible for updating the CGU size // estimates. @@ -179,59 +181,34 @@ where // local functions the definition of which is marked with `#[inline]`. { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(cx, &mut codegen_units) - }; + place_inlined_mono_items(cx, &mut codegen_units); - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); + for cgu in &mut codegen_units { + cgu.create_size_estimate(tcx); + } + + debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); } - debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); - // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. if !tcx.sess.link_dead_code() { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(cx, &mut codegen_units, internalization_candidates); + + debug_dump(tcx, "INTERNALIZE", &codegen_units, unique_inlined_stats); } + // Mark one CGU for dead code, if necessary. let instrument_dead_code = tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); - if instrument_dead_code { - assert!( - codegen_units.len() > 0, - "There must be at least one CGU that code coverage data can be generated in." - ); - - // Find the smallest CGU that has exported symbols and put the dead - // function stubs in that CGU. We look for exported symbols to increase - // the likelihood the linker won't throw away the dead functions. - // FIXME(#92165): In order to truly resolve this, we need to make sure - // the object file (CGU) containing the dead function stubs is included - // in the final binary. This will probably require forcing these - // function symbols to be included via `-u` or `/include` linker args. - let mut cgus: Vec<_> = codegen_units.iter_mut().collect(); - cgus.sort_by_key(|cgu| cgu.size_estimate()); - - let dead_code_cgu = - if let Some(cgu) = cgus.into_iter().rev().find(|cgu| { - cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External) - }) { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut codegen_units[0] - }; - dead_code_cgu.make_code_coverage_dead_code_cgu(); + mark_code_coverage_dead_code_cgu(&mut codegen_units); } // Ensure CGUs are sorted by name, so that we get deterministic results. assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); - debug_dump(tcx, "FINAL", &codegen_units, unique_inlined_stats); - codegen_units } @@ -363,9 +340,7 @@ fn merge_codegen_units<'tcx>( // Move the mono-items from `smallest` to `second_smallest` second_smallest.modify_size_estimate(smallest.size_estimate()); - for (k, v) in smallest.items_mut().drain() { - second_smallest.items_mut().insert(k, v); - } + second_smallest.items_mut().extend(smallest.items_mut().drain()); // Record that `second_smallest` now contains all the stuff that was // in `smallest` before. @@ -545,6 +520,28 @@ fn internalize_symbols<'tcx>( } } +fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>]) { + assert!(!codegen_units.is_empty()); + + // Find the smallest CGU that has exported symbols and put the dead + // function stubs in that CGU. We look for exported symbols to increase + // the likelihood the linker won't throw away the dead functions. + // FIXME(#92165): In order to truly resolve this, we need to make sure + // the object file (CGU) containing the dead function stubs is included + // in the final binary. This will probably require forcing these + // function symbols to be included via `-u` or `/include` linker args. + let dead_code_cgu = codegen_units + .iter_mut() + .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) + .min_by_key(|cgu| cgu.size_estimate()); + + // If there are no CGUs that have externally linked items, then we just + // pick the first CGU as a fallback. + let dead_code_cgu = if let Some(cgu) = dead_code_cgu { cgu } else { &mut codegen_units[0] }; + + dead_code_cgu.make_code_coverage_dead_code_cgu(); +} + fn characteristic_def_id_of_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: MonoItem<'tcx>, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d81b38992014..57202ac9c6e2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2029,17 +2029,14 @@ impl<'a> Parser<'a> { let recovered = self.recover_after_dot(); let token = recovered.as_ref().unwrap_or(&self.token); match token::Lit::from_token(token) { - Some(token_lit) => { - match MetaItemLit::from_token_lit(token_lit, token.span) { + Some(lit) => { + match MetaItemLit::from_token_lit(lit, token.span) { Ok(lit) => { self.bump(); Some(lit) } Err(err) => { - let span = token.span; - let token::Literal(lit) = token.kind else { - unreachable!(); - }; + let span = token.uninterpolated_span(); self.bump(); report_lit_error(&self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a51a1c9a8a43..5ef11acadced 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -242,6 +242,9 @@ where } } } + ty::Alias(ty::Weak, alias) => { + self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty); + } ty::Alias(ty::Projection, proj) => { if self.def_id_visitor.skip_assoc_tys() { // Visitors searching for minimal visibility/reachability want to diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 0c7e36b3bef7..9f2ff4378425 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -507,7 +507,7 @@ impl HygieneData { self.normalize_to_macro_rules(call_site_ctxt) }; - if call_site_ctxt == SyntaxContext::root() { + if call_site_ctxt.is_root() { return self.apply_mark_internal(ctxt, expn_id, transparency); } @@ -671,12 +671,17 @@ impl SyntaxContext { } #[inline] - pub(crate) fn as_u32(self) -> u32 { + pub const fn is_root(self) -> bool { + self.0 == SyntaxContext::root().as_u32() + } + + #[inline] + pub(crate) const fn as_u32(self) -> u32 { self.0 } #[inline] - pub(crate) fn from_u32(raw: u32) -> SyntaxContext { + pub(crate) const fn from_u32(raw: u32) -> SyntaxContext { SyntaxContext(raw) } @@ -1500,7 +1505,7 @@ impl HashStable for SyntaxContext { const TAG_EXPANSION: u8 = 0; const TAG_NO_EXPANSION: u8 = 1; - if *self == SyntaxContext::root() { + if self.is_root() { TAG_NO_EXPANSION.hash_stable(ctx, hasher); } else { TAG_EXPANSION.hash_stable(ctx, hasher); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index eae3f0fa041d..e7a53c63e83b 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -826,9 +826,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::root() { + if span_data.ctxt.is_root() { return end; - } else if end_data.ctxt == SyntaxContext::root() { + } else if end_data.ctxt.is_root() { return self; } // Both spans fall within a macro. @@ -837,7 +837,7 @@ impl Span { Span::new( cmp::min(span_data.lo, end_data.lo), cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if span_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } @@ -855,7 +855,7 @@ impl Span { Span::new( span.hi, end.lo, - if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, + if end.ctxt.is_root() { end.ctxt } else { span.ctxt }, if span.parent == end.parent { span.parent } else { None }, ) } @@ -879,9 +879,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::root() { + if span_data.ctxt.is_root() { return end; - } else if end_data.ctxt == SyntaxContext::root() { + } else if end_data.ctxt.is_root() { return self; } // Both spans fall within a macro. @@ -890,7 +890,7 @@ impl Span { Span::new( span_data.lo, end_data.lo, - if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if end_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c5ce2575fff0..19d986a3152b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1156,6 +1156,7 @@ symbols! { ptr_null_mut, ptr_offset_from, ptr_offset_from_unsigned, + ptr_unique, pub_macro_rules, pub_restricted, public, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 0a805e2422d4..5dc00e317863 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -483,6 +483,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { } ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"), + ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"), ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"), ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"), } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1b749b9c854c..543611daae83 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -105,7 +105,7 @@ pub(super) trait GoalKind<'tcx>: fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx>; @@ -115,7 +115,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, requirements: impl IntoIterator>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { @@ -131,7 +131,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_alias_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { ecx.validate_alias_bound_self_from_param_env(goal) @@ -144,7 +144,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { let tcx = ecx.tcx(); @@ -467,11 +467,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - match G::consider_implied_clause(self, goal, assumption, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_implied_clause(self, goal, clause, []) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -508,20 +510,23 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Alias(ty::Inherent, _) + | ty::Alias(ty::Weak, _) | ty::Error(_) => return, ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty, }; for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs) { - match G::consider_alias_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_alias_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -675,18 +680,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // projection predicates that we reach by elaborating the principal trait ref, // since that'll cause ambiguity. // - // We can remove this when we have implemented intersections in responses. + // We can remove this when we have implemented lifetime intersections in responses. if assumption.to_opt_poly_projection_pred().is_some() && !own_bounds.contains(&assumption) { continue; } - match G::consider_object_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_object_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 0f3f8f1ac2cb..97b86a06c8ca 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -33,7 +33,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => { diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 29bdb5ff67da..05248cb9d178 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -208,8 +208,25 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r = self.infcx.shallow_resolve(r); + fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match self.canonicalize_mode { + CanonicalizeMode::Input => { + // Don't resolve infer vars in input, since it affects + // caching and may cause trait selection bugs which rely + // on regions to be equal. + } + CanonicalizeMode::Response { .. } => { + if let ty::ReVar(vid) = *r { + r = self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(self.infcx.tcx, vid); + } + } + } + let kind = match *r { ty::ReLateBound(..) => return r, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index a8a0e1ebfb42..8592fc164d04 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -263,7 +263,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let (_orig_values, canonical_goal) = self.canonicalize_goal(goal); let new_canonical_response = EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?; - if !new_canonical_response.value.var_values.is_identity() { + // We only check for modulo regions as we convert all regions in + // the input to new existentials, even if they're expected to be + // `'static` or a placeholder region. + if !new_canonical_response.value.var_values.is_identity_modulo_regions() { bug!( "unstable result: re-canonicalized goal={canonical_goal:#?} \ first_response={canonical_response:#?} \ diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f4c29c837b88..a30a14df80b0 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -29,6 +29,7 @@ mod opaques; mod project_goals; mod search_graph; mod trait_goals; +mod weak_types; pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt}; pub use fulfill::FulfillmentCtxt; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 242f9ba87473..e9600968f48c 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -57,6 +57,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } DefKind::AnonConst => self.normalize_anon_const(goal), DefKind::OpaqueTy => self.normalize_opaque_type(goal), + DefKind::TyAlias => self.normalize_weak_type(goal), kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), } } @@ -105,15 +106,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() - && poly_projection_pred.projection_def_id() == goal.predicate.def_id() + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.projection_def_id() == goal.predicate.def_id() { ecx.probe(|ecx| { let assumption_projection_pred = - ecx.instantiate_binder_with_infer(poly_projection_pred); + ecx.instantiate_binder_with_infer(projection_pred); ecx.eq( goal.param_env, goal.predicate.projection_ty, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f722f281314e..279fc1229d42 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -81,17 +81,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() - && poly_trait_pred.def_id() == goal.predicate.def_id() - && poly_trait_pred.polarity() == goal.predicate.polarity + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.def_id() == goal.predicate.def_id() + && trait_clause.polarity() == goal.predicate.polarity { // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = - ecx.instantiate_binder_with_infer(poly_trait_pred); + ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( goal.param_env, goal.predicate.trait_ref, @@ -618,7 +618,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..) | ty::Placeholder(..) => Some(Err(NoSolution)), ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"), diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs new file mode 100644 index 000000000000..b095b54c554f --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs @@ -0,0 +1,19 @@ +use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; +use rustc_middle::ty; + +use super::EvalCtxt; + +impl<'tcx> EvalCtxt<'_, 'tcx> { + pub(super) fn normalize_weak_type( + &mut self, + goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>, + ) -> QueryResult<'tcx> { + let tcx = self.tcx(); + let weak_ty = goal.predicate.projection_ty; + let expected = goal.predicate.term.ty().expect("no such thing as a const alias"); + + let actual = tcx.type_of(weak_ty.def_id).subst(tcx, weak_ty.substs); + self.eq(goal.param_env, expected, actual)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } +} diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 190a78f6a8ec..0065c7fc253b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -292,7 +292,12 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) }) .chain(obligations) - .find(|o| !selcx.predicate_may_hold_fatal(o)); + .find(|o| { + selcx.evaluate_root_obligation(o).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + }); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); @@ -690,7 +695,9 @@ impl<'tcx> TypeVisitor> for OrphanChecker<'tcx> { | ty::RawPtr(..) | ty::Never | ty::Tuple(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) => self.found_non_local_ty(ty), + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) => { + self.found_non_local_ty(ty) + } ty::Param(..) => self.found_param_ty(ty), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 1bc4599377aa..ffbe2888bf84 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1824,12 +1824,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Alias(ty::Projection, ..) => Some(12), ty::Alias(ty::Inherent, ..) => Some(13), ty::Alias(ty::Opaque, ..) => Some(14), - ty::Never => Some(15), - ty::Adt(..) => Some(16), - ty::Generator(..) => Some(17), - ty::Foreign(..) => Some(18), - ty::GeneratorWitness(..) => Some(19), - ty::GeneratorWitnessMIR(..) => Some(20), + ty::Alias(ty::Weak, ..) => Some(15), + ty::Never => Some(16), + ty::Adt(..) => Some(17), + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::GeneratorWitnessMIR(..) => Some(21), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5783383e93e3..fcf813e3a393 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3198,6 +3198,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) }); } + ObligationCauseCode::TypeAlias(ref nested, span, def_id) => { + // #74711: avoid a stack overflow + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + body_id, + err, + predicate, + param_env, + nested, + obligated_types, + seen_requirements, + ) + }); + let mut multispan = MultiSpan::from(span); + multispan.push_span_label(span, "required by this bound"); + err.span_note( + multispan, + format!( + "required by a bound on the type alias `{}`", + self.infcx.tcx.item_name(def_id) + ), + ); + } ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index f8d056e321e6..ff55eaf13ad5 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId; pub use rustc_middle::traits::query::OutlivesBound; -type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; +pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { fn implied_outlives_bounds( &self, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0a1e971f268e..8399fbfc5be6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -3,6 +3,7 @@ use super::specialization_graph; use super::translate_substs; use super::util; +use super::ImplSourceUserDefinedData; use super::MismatchedProjectionTypes; use super::Obligation; use super::ObligationCause; @@ -10,10 +11,6 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::{ - ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, - ImplSourceUserDefinedData, -}; use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; use crate::errors::InherentProjectionNormalizationOverflow; @@ -30,7 +27,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::ImplSourceBuiltinData; +use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; @@ -621,6 +618,30 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ); normalized_ty } + ty::Weak => { + let infcx = self.selcx.infcx; + self.obligations.extend( + infcx + .tcx + .predicates_of(data.def_id) + .instantiate_own(infcx.tcx, data.substs) + .map(|(mut predicate, span)| { + if data.has_escaping_bound_vars() { + (predicate, ..) = BoundVarReplacer::replace_bound_vars( + infcx, + &mut self.universes, + predicate, + ); + } + let mut cause = self.cause.clone(); + cause.map_code(|code| { + ObligationCauseCode::TypeAlias(code, span, data.def_id) + }); + Obligation::new(infcx.tcx, cause, self.param_env, predicate) + }), + ); + infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self) + } ty::Inherent if !data.has_escaping_bound_vars() => { // This branch is *mostly* just an optimization: when we don't @@ -1545,7 +1566,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // Check whether the self-type is itself a projection. // If so, extract what we know from the trait and try to come up with a good answer. let bounds = match *obligation.predicate.self_ty().kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, ref data) => { tcx.item_bounds(data.def_id).subst(tcx, data.substs) } @@ -1696,11 +1717,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }; let eligible = match &impl_source { - super::ImplSource::Closure(_) - | super::ImplSource::Generator(_) - | super::ImplSource::Future(_) - | super::ImplSource::FnPointer(_) - | super::ImplSource::TraitAlias(_) => true, + super::ImplSource::TraitAlias(_) => true, super::ImplSource::UserDefined(impl_data) => { // We have to be careful when projecting out of an // impl because of specialization. If we are not in @@ -1758,7 +1775,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let lang_items = selcx.tcx().lang_items(); - if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { + if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id())) + || selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some() + { + true + } else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { match self_ty.kind() { ty::Bool | ty::Char @@ -1905,9 +1926,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // why we special case object types. false } - super::ImplSource::AutoImpl(..) - | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::ConstDestruct(_) => { + | super::ImplSource::TraitUpcasting(_) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -1971,17 +1990,27 @@ fn confirm_select_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { match impl_source { super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), - super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), - super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data), - super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data), - super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), - super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data), + super::ImplSource::Builtin(data) => { + let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx()); + let lang_items = selcx.tcx().lang_items(); + if lang_items.gen_trait() == Some(trait_def_id) { + confirm_generator_candidate(selcx, obligation, data) + } else if lang_items.future_trait() == Some(trait_def_id) { + confirm_future_candidate(selcx, obligation, data) + } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() { + if obligation.predicate.self_ty().is_closure() { + confirm_closure_candidate(selcx, obligation, data) + } else { + confirm_fn_pointer_candidate(selcx, obligation, data) + } + } else { + confirm_builtin_candidate(selcx, obligation, data) + } + } super::ImplSource::Object(_) - | super::ImplSource::AutoImpl(..) | super::ImplSource::Param(..) | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::TraitAlias(..) - | super::ImplSource::ConstDestruct(_) => { + | super::ImplSource::TraitAlias(..) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, @@ -1995,9 +2024,14 @@ fn confirm_select_candidate<'cx, 'tcx>( fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let ty::Generator(_, substs, _) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let gen_sig = substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2035,16 +2069,21 @@ fn confirm_generator_candidate<'cx, 'tcx>( }); confirm_param_env_candidate(selcx, obligation, predicate, false) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } fn confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let ty::Generator(_, substs, _) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let gen_sig = substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2074,14 +2113,14 @@ fn confirm_future_candidate<'cx, 'tcx>( }); confirm_param_env_candidate(selcx, obligation, predicate, false) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } fn confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - data: ImplSourceBuiltinData>, + data: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); @@ -2129,15 +2168,15 @@ fn confirm_builtin_candidate<'cx, 'tcx>( confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) .with_addl_obligations(obligations) - .with_addl_obligations(data.nested) + .with_addl_obligations(data) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let fn_type = selcx.infcx.shallow_resolve(fn_pointer_impl_source.fn_ty); + let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let sig = fn_type.fn_sig(selcx.tcx()); let Normalized { value: sig, obligations } = normalize_with_depth( selcx, @@ -2148,16 +2187,21 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( ); confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) - .with_addl_obligations(fn_pointer_impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let closure_sig = impl_source.substs.as_closure().sig(); + let ty::Closure(_, substs) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let closure_sig = substs.as_closure().sig(); let Normalized { value: closure_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2169,7 +2213,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate"); confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 8bf934cb78ae..2d97a8082258 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -257,7 +257,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> ty::Opaque => ty.try_super_fold_with(self)?, - ty::Projection | ty::Inherent => { + ty::Projection | ty::Inherent | ty::Weak => { // See note in `rustc_trait_selection::traits::project` let infcx = self.infcx; @@ -282,6 +282,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> debug!("QueryNormalizer: orig_values = {:#?}", orig_values); let result = match kind { ty::Projection => tcx.normalize_projection_ty(c_data), + ty::Weak => tcx.normalize_weak_ty(c_data), ty::Inherent => tcx.normalize_inherent_projection_ty(c_data), _ => unreachable!(), }?; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3c223db5a0b7..f2dfa6921f41 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -143,7 +143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Before we go into the whole placeholder thing, just // quickly check if the self-type is a projection at all. match obligation.predicate.skip_binder().trait_ref.self_ty().kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, _) => {} ty::Infer(ty::TyVar(_)) => { span_bug!( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7853af959ad5..3c356978d5ca 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -27,11 +27,9 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, - ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData, - ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData, - ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation, - ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError, + ImplSourceObjectData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, + ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, + OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, }; @@ -72,7 +70,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { AutoImplCandidate => { let data = self.confirm_auto_impl_candidate(obligation); - ImplSource::AutoImpl(data) + ImplSource::Builtin(data) } ProjectionCandidate(idx, constness) => { @@ -87,22 +85,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ClosureCandidate { .. } => { let vtable_closure = self.confirm_closure_candidate(obligation)?; - ImplSource::Closure(vtable_closure) + ImplSource::Builtin(vtable_closure) } GeneratorCandidate => { let vtable_generator = self.confirm_generator_candidate(obligation)?; - ImplSource::Generator(vtable_generator) + ImplSource::Builtin(vtable_generator) } FutureCandidate => { let vtable_future = self.confirm_future_candidate(obligation)?; - ImplSource::Future(vtable_future) + ImplSource::Builtin(vtable_future) } FnPointerCandidate { is_const } => { let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; - ImplSource::FnPointer(data) + ImplSource::Builtin(data) } TraitAliasCandidate => { @@ -114,7 +112,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst) + ImplSource::Builtin(Vec::new()) } BuiltinUnsizeCandidate => { @@ -129,7 +127,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ConstDestructCandidate(def_id) => { let data = self.confirm_const_destruct_candidate(obligation, def_id)?; - ImplSource::ConstDestruct(data) + ImplSource::Builtin(data) } }; @@ -163,7 +161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { (def_id, substs) } @@ -244,7 +242,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, has_nested: bool, - ) -> ImplSourceBuiltinData> { + ) -> Vec> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let lang_items = self.tcx().lang_items(); @@ -277,14 +275,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligations); - ImplSourceBuiltinData { nested: obligations } + obligations } #[instrument(level = "debug", skip(self))] fn confirm_transmutability_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { use rustc_transmute::{Answer, Condition}; #[instrument(level = "debug", skip(tcx, obligation, predicate))] fn flatten_answer_tree<'tcx>( @@ -369,7 +367,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; debug!(?fully_flattened); - Ok(ImplSourceBuiltinData { nested: fully_flattened }) + Ok(fully_flattened) } /// This handles the case where an `auto trait Foo` impl is being used. @@ -380,7 +378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_auto_impl_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> ImplSourceAutoImplData> { + ) -> Vec> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -394,7 +392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_def_id: DefId, nested: ty::Binder<'tcx, Vec>>, - ) -> ImplSourceAutoImplData> { + ) -> Vec> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(BuiltinDerivedObligation); @@ -424,7 +422,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligations, "vtable_auto_impl"); - ImplSourceAutoImplData { trait_def_id, nested: obligations } + obligations }) } @@ -487,7 +485,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, index: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); @@ -654,15 +652,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)), ); - Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }) + Ok(ImplSourceObjectData { + upcast_trait_def_id: upcast_trait_ref.def_id(), + vtable_base, + nested, + }) } fn confirm_fn_pointer_candidate( &mut self, obligation: &TraitObligation<'tcx>, is_const: bool, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); let tcx = self.tcx(); @@ -714,7 +715,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]); nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr)); - Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested }) + Ok(nested) } fn confirm_trait_alias_candidate( @@ -746,8 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_generator_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. @@ -780,13 +780,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?trait_ref, ?nested, "generator candidate obligations"); - Ok(ImplSourceGeneratorData { generator_def_id, substs, nested }) + Ok(nested) } fn confirm_future_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. @@ -810,14 +810,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?trait_ref, ?nested, "future candidate obligations"); - Ok(ImplSourceFutureData { generator_def_id, substs, nested }) + Ok(nested) } #[instrument(skip(self), level = "debug")] fn confirm_closure_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let kind = self .tcx() .fn_trait_kind_from_def_id(obligation.predicate.def_id()) @@ -844,7 +844,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )); } - Ok(ImplSourceClosureData { closure_def_id, substs, nested }) + Ok(nested) } /// In the case of closure types and fn pointers, @@ -912,8 +912,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, idx: usize, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -1010,13 +1009,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let vtable_vptr_slot = prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap(); - Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested }) + Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) } fn confirm_builtin_unsize_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -1217,17 +1216,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("source: {source}, target: {target}"), }; - Ok(ImplSourceBuiltinData { nested }) + Ok(nested) } fn confirm_const_destruct_candidate( &mut self, obligation: &TraitObligation<'tcx>, impl_def_id: Option, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` if !obligation.is_const() { - return Ok(ImplSourceConstDestructData { nested: vec![] }); + return Ok(vec![]); } let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); @@ -1381,6 +1380,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - Ok(ImplSourceConstDestructData { nested }) + Ok(nested) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5acd7b573dd9..e72d3ca97d7c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -518,19 +518,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The result is "true" if the obligation *may* hold and "false" if // we can be sure it does not. - /// Evaluates whether the obligation `obligation` can be satisfied (by any means). - pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool { - debug!(?obligation, "predicate_may_hold_fatal"); - - // This fatal query is a stopgap that should only be used in standard mode, - // where we do not expect overflow to be propagated. - assert!(self.query_mode == TraitQueryMode::Standard); - - self.evaluate_root_obligation(obligation) - .expect("Overflow should be caught earlier in standard query mode") - .may_apply() - } - /// Evaluates whether the obligation `obligation` can be satisfied /// and returns an `EvaluationResult`. This is meant for the /// *initial* call. @@ -2327,7 +2314,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("asked to assemble constituent types of unexpected type: {:?}", t); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 537405b7eb91..906c357e8ca7 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -243,12 +243,12 @@ pub fn upcast_choices<'tcx>( /// `object.upcast_trait_ref`) within the vtable for `object`. pub fn get_vtable_index_of_object_method<'tcx, N>( tcx: TyCtxt<'tcx>, - object: &super::ImplSourceObjectData<'tcx, N>, + object: &super::ImplSourceObjectData, method_def_id: DefId, ) -> Option { // Count number of methods preceding the one we are selecting and // add them to the total offset. - tcx.own_existential_vtable_entries(object.upcast_trait_ref.def_id()) + tcx.own_existential_vtable_entries(object.upcast_trait_def_id) .iter() .copied() .position(|def_id| def_id == method_def_id) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 086ab32b5200..92d899b0f138 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -731,6 +731,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => { + let obligations = self.nominal_obligations(def_id, substs); + self.out.extend(obligations); + } + ty::Dynamic(data, r, _) => { // WfObject // diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e6c6e0f13df3..f9a7c8c386ae 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -372,6 +372,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substitution: substs.lower_into(interner), })) } + ty::Alias(ty::Weak, ty::AliasTy { .. }) => unimplemented!(), ty::Alias(ty::Inherent, _) => unimplemented!(), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index b552ba41acd3..83828f177bc8 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -10,7 +10,12 @@ use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext}; use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { - *p = Providers { normalize_projection_ty, normalize_inherent_projection_ty, ..*p }; + *p = Providers { + normalize_projection_ty, + normalize_weak_ty, + normalize_inherent_projection_ty, + ..*p + }; } fn normalize_projection_ty<'tcx>( @@ -43,6 +48,33 @@ fn normalize_projection_ty<'tcx>( ) } +fn normalize_weak_ty<'tcx>( + tcx: TyCtxt<'tcx>, + goal: CanonicalProjectionGoal<'tcx>, +) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { + debug!("normalize_provider(goal={:#?})", goal); + + tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); + tcx.infer_ctxt().enter_canonical_trait_query( + &goal, + |ocx, ParamEnvAnd { param_env, value: goal }| { + let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.substs).map( + |(predicate, span)| { + traits::Obligation::new( + tcx, + ObligationCause::dummy_with_span(span), + param_env, + predicate, + ) + }, + ); + ocx.register_obligations(obligations); + let normalized_ty = tcx.type_of(goal.def_id).subst(tcx, goal.substs); + Ok(NormalizationResult { normalized_ty }) + }, + ) +} + fn normalize_inherent_projection_ty<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalProjectionGoal<'tcx>, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index dd911239ac45..45b1075b6023 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -177,85 +177,6 @@ fn resolve_associated_item<'tcx>( Some(ty::Instance::new(leaf_def.item.def_id, substs)) } - traits::ImplSource::Generator(generator_data) => { - if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { - // For compiler developers who'd like to add new items to `Generator`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - span_bug!( - tcx.def_span(generator_data.generator_def_id), - "no definition for `{trait_ref}::{}` for built-in generator type", - tcx.item_name(trait_item_id) - ) - } - Some(Instance { - def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs, - }) - } - traits::ImplSource::Future(future_data) => { - if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { - // `Future::poll` is generated by the compiler. - Some(Instance { - def: ty::InstanceDef::Item(future_data.generator_def_id), - substs: future_data.substs, - }) - } else { - // All other methods are default methods of the `Future` trait. - // (this assumes that `ImplSource::Future` is only used for methods on `Future`) - debug_assert!(tcx.defaultness(trait_item_id).has_value()); - Some(Instance::new(trait_item_id, rcvr_substs)) - } - } - traits::ImplSource::Closure(closure_data) => { - if cfg!(debug_assertions) - && ![sym::call, sym::call_mut, sym::call_once] - .contains(&tcx.item_name(trait_item_id)) - { - // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - span_bug!( - tcx.def_span(closure_data.closure_def_id), - "no definition for `{trait_ref}::{}` for built-in closure type", - tcx.item_name(trait_item_id) - ) - } - let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); - Instance::resolve_closure( - tcx, - closure_data.closure_def_id, - closure_data.substs, - trait_closure_kind, - ) - } - traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() { - ty::FnDef(..) | ty::FnPtr(..) => { - if cfg!(debug_assertions) - && ![sym::call, sym::call_mut, sym::call_once] - .contains(&tcx.item_name(trait_item_id)) - { - // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - bug!( - "no definition for `{trait_ref}::{}` for built-in fn type", - tcx.item_name(trait_item_id) - ) - } - Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty), - substs: rcvr_substs, - }) - } - _ => bug!( - "no built-in definition for `{trait_ref}::{}` for non-fn type", - tcx.item_name(trait_item_id) - ), - }, traits::ImplSource::Object(ref data) => { traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { Instance { @@ -308,15 +229,73 @@ fn resolve_associated_item<'tcx>( span: tcx.def_span(trait_item_id), }) } + } else if Some(trait_ref.def_id) == lang_items.future_trait() { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + bug!() + }; + if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { + // `Future::poll` is generated by the compiler. + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs }) + } else { + // All other methods are default methods of the `Future` trait. + // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`) + debug_assert!(tcx.defaultness(trait_item_id).has_value()); + Some(Instance::new(trait_item_id, rcvr_substs)) + } + } else if Some(trait_ref.def_id) == lang_items.gen_trait() { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + bug!() + }; + if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { + // For compiler developers who'd like to add new items to `Generator`, + // you either need to generate a shim body, or perhaps return + // `InstanceDef::Item` pointing to a trait default method body if + // it is given a default implementation by the trait. + span_bug!( + tcx.def_span(generator_def_id), + "no definition for `{trait_ref}::{}` for built-in generator type", + tcx.item_name(trait_item_id) + ) + } + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs }) + } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { + // FIXME: This doesn't check for malformed libcore that defines, e.g., + // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension + // methods. + if cfg!(debug_assertions) + && ![sym::call, sym::call_mut, sym::call_once] + .contains(&tcx.item_name(trait_item_id)) + { + // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, + // you either need to generate a shim body, or perhaps return + // `InstanceDef::Item` pointing to a trait default method body if + // it is given a default implementation by the trait. + bug!( + "no definition for `{trait_ref}::{}` for built-in callable type", + tcx.item_name(trait_item_id) + ) + } + match *rcvr_substs.type_at(0).kind() { + ty::Closure(closure_def_id, substs) => { + let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); + Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind) + } + ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { + def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)), + substs: rcvr_substs, + }), + _ => bug!( + "no built-in definition for `{trait_ref}::{}` for non-fn type", + tcx.item_name(trait_item_id) + ), + } } else { None } } - traits::ImplSource::AutoImpl(..) - | traits::ImplSource::Param(..) + traits::ImplSource::Param(..) | traits::ImplSource::TraitAlias(..) - | traits::ImplSource::TraitUpcasting(_) - | traits::ImplSource::ConstDestruct(_) => None, + | traits::ImplSource::TraitUpcasting(_) => None, }) } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index fa18f921ee4b..f621673f1d6f 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -36,9 +36,17 @@ pub enum DynKind { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] pub enum AliasKind { + /// A projection `::AssocType`. + /// Can get normalized away if monomorphic enough. Projection, Inherent, + /// An opaque type (usually from `impl Trait` in type aliases or function return types) + /// Can only be normalized away in RevealAll mode Opaque, + /// A type alias that actually checks its trait bounds. + /// Currently only used if the type alias references opaque types. + /// Can always be normalized away. + Weak, } /// Defines the kinds of types used by the type system. diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 59fa91c1066d..967ad3a0e690 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -56,6 +56,11 @@ //! [`Rc`]: rc //! [`RefCell`]: core::cell +// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] #![doc( @@ -75,11 +80,6 @@ ))] #![no_std] #![needs_allocator] -// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// // Lints: #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index a853f15edb7e..ff7e91d3ec30 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -32,6 +32,8 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] +// Lang item used experimentally by Miri to define the semantics of `Unique`. +#[cfg_attr(not(bootstrap), lang = "ptr_unique")] pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 4f339a18a480..3edf9d747ce8 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -47,9 +47,9 @@ use buffer::Buffer; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct BufReader { - inner: R, +pub struct BufReader { buf: Buffer, + inner: R, } impl BufReader { @@ -95,7 +95,7 @@ impl BufReader { } } -impl BufReader { +impl BufReader { /// Gets a reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. @@ -213,7 +213,10 @@ impl BufReader { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(self) -> R { + pub fn into_inner(self) -> R + where + R: Sized, + { self.inner } @@ -226,13 +229,13 @@ impl BufReader { // This is only used by a test which asserts that the initialization-tracking is correct. #[cfg(test)] -impl BufReader { +impl BufReader { pub fn initialized(&self) -> usize { self.buf.initialized() } } -impl BufReader { +impl BufReader { /// Seeks relative to the current position. If the new position lies within the buffer, /// the buffer will not be flushed, allowing for more efficient seeks. /// This method does not return the location of the underlying reader, so the caller @@ -257,7 +260,7 @@ impl BufReader { } #[stable(feature = "rust1", since = "1.0.0")] -impl Read for BufReader { +impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer @@ -371,7 +374,7 @@ impl Read for BufReader { } #[stable(feature = "rust1", since = "1.0.0")] -impl BufRead for BufReader { +impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.buf.fill_buf(&mut self.inner) } @@ -384,11 +387,11 @@ impl BufRead for BufReader { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for BufReader where - R: fmt::Debug, + R: ?Sized + fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufReader") - .field("reader", &self.inner) + .field("reader", &&self.inner) .field( "buffer", &format_args!("{}/{}", self.buf.filled() - self.buf.pos(), self.capacity()), @@ -398,7 +401,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Seek for BufReader { +impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with [SeekFrom::Current]\(_) is the @@ -491,7 +494,7 @@ impl Seek for BufReader { } } -impl SizeHint for BufReader { +impl SizeHint for BufReader { #[inline] fn lower_bound(&self) -> usize { SizeHint::lower_bound(self.get_ref()) + self.buffer().len() diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 14c455d4fa3c..0e2450655e5b 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -67,8 +67,7 @@ use crate::ptr; /// [`TcpStream`]: crate::net::TcpStream /// [`flush`]: BufWriter::flush #[stable(feature = "rust1", since = "1.0.0")] -pub struct BufWriter { - inner: W, +pub struct BufWriter { // The buffer. Avoid using this like a normal `Vec` in common code paths. // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other // methods that require bounds checking or the like. This makes an enormous @@ -78,6 +77,7 @@ pub struct BufWriter { // write the buffered data a second time in BufWriter's destructor. This // flag tells the Drop impl if it should skip the flush. panicked: bool, + inner: W, } impl BufWriter { @@ -115,6 +115,69 @@ impl BufWriter { BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false } } + /// Unwraps this `BufWriter`, returning the underlying writer. + /// + /// The buffer is written out before returning the writer. + /// + /// # Errors + /// + /// An [`Err`] will be returned if an error occurs while flushing the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // unwrap the TcpStream and flush the buffer + /// let stream = buffer.into_inner().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_inner(mut self) -> Result>> { + match self.flush_buf() { + Err(e) => Err(IntoInnerError::new(self, e)), + Ok(()) => Ok(self.into_parts().0), + } + } + + /// Disassembles this `BufWriter`, returning the underlying writer, and any buffered but + /// unwritten data. + /// + /// If the underlying writer panicked, it is not known what portion of the data was written. + /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer + /// contents can still be recovered). + /// + /// `into_parts` makes no attempt to flush data and cannot fail. + /// + /// # Examples + /// + /// ``` + /// use std::io::{BufWriter, Write}; + /// + /// let mut buffer = [0u8; 10]; + /// let mut stream = BufWriter::new(buffer.as_mut()); + /// write!(stream, "too much data").unwrap(); + /// stream.flush().expect_err("it doesn't fit"); + /// let (recovered_writer, buffered_data) = stream.into_parts(); + /// assert_eq!(recovered_writer.len(), 0); + /// assert_eq!(&buffered_data.unwrap(), b"ata"); + /// ``` + #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] + pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { + let buf = mem::take(&mut self.buf); + let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; + + // SAFETY: forget(self) prevents double dropping inner + let inner = unsafe { ptr::read(&self.inner) }; + mem::forget(self); + + (inner, buf) + } +} + +impl BufWriter { /// Send data in our local buffer into the inner writer, looping as /// necessary until either it's all been sent or an error occurs. /// @@ -284,67 +347,6 @@ impl BufWriter { self.buf.capacity() } - /// Unwraps this `BufWriter`, returning the underlying writer. - /// - /// The buffer is written out before returning the writer. - /// - /// # Errors - /// - /// An [`Err`] will be returned if an error occurs while flushing the buffer. - /// - /// # Examples - /// - /// ```no_run - /// use std::io::BufWriter; - /// use std::net::TcpStream; - /// - /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); - /// - /// // unwrap the TcpStream and flush the buffer - /// let stream = buffer.into_inner().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(mut self) -> Result>> { - match self.flush_buf() { - Err(e) => Err(IntoInnerError::new(self, e)), - Ok(()) => Ok(self.into_parts().0), - } - } - - /// Disassembles this `BufWriter`, returning the underlying writer, and any buffered but - /// unwritten data. - /// - /// If the underlying writer panicked, it is not known what portion of the data was written. - /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer - /// contents can still be recovered). - /// - /// `into_parts` makes no attempt to flush data and cannot fail. - /// - /// # Examples - /// - /// ``` - /// use std::io::{BufWriter, Write}; - /// - /// let mut buffer = [0u8; 10]; - /// let mut stream = BufWriter::new(buffer.as_mut()); - /// write!(stream, "too much data").unwrap(); - /// stream.flush().expect_err("it doesn't fit"); - /// let (recovered_writer, buffered_data) = stream.into_parts(); - /// assert_eq!(recovered_writer.len(), 0); - /// assert_eq!(&buffered_data.unwrap(), b"ata"); - /// ``` - #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] - pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { - let buf = mem::take(&mut self.buf); - let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; - - // SAFETY: forget(self) prevents double dropping inner - let inner = unsafe { ptr::read(&self.inner) }; - mem::forget(self); - - (inner, buf) - } - // Ensure this function does not get inlined into `write`, so that it // remains inlineable and its common path remains as short as possible. // If this function ends up being called frequently relative to `write`, @@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked { } #[stable(feature = "rust1", since = "1.0.0")] -impl Write for BufWriter { +impl Write for BufWriter { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { // Use < instead of <= to avoid a needless trip through the buffer in some cases. @@ -640,20 +642,20 @@ impl Write for BufWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufWriter +impl fmt::Debug for BufWriter where W: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufWriter") - .field("writer", &self.inner) + .field("writer", &&self.inner) .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) .finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Seek for BufWriter { +impl Seek for BufWriter { /// Seek to the offset, in bytes, in the underlying writer. /// /// Seeking always writes out the internal buffer before seeking. @@ -664,7 +666,7 @@ impl Seek for BufWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for BufWriter { +impl Drop for BufWriter { fn drop(&mut self) { if !self.panicked { // dtors should not panic, so we ignore a failed flush diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs index a26a4ab330e7..3d4ae7041932 100644 --- a/library/std/src/io/buffered/linewriter.rs +++ b/library/std/src/io/buffered/linewriter.rs @@ -64,7 +64,7 @@ use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSli /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct LineWriter { +pub struct LineWriter { inner: BufWriter, } @@ -109,27 +109,6 @@ impl LineWriter { LineWriter { inner: BufWriter::with_capacity(capacity, inner) } } - /// Gets a reference to the underlying writer. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::io::LineWriter; - /// - /// fn main() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); - /// - /// let reference = file.get_ref(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_ref(&self) -> &W { - self.inner.get_ref() - } - /// Gets a mutable reference to the underlying writer. /// /// Caution must be taken when calling methods on the mutable reference @@ -184,8 +163,31 @@ impl LineWriter { } } +impl LineWriter { + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// + /// let reference = file.get_ref(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } +} + #[stable(feature = "rust1", since = "1.0.0")] -impl Write for LineWriter { +impl Write for LineWriter { fn write(&mut self, buf: &[u8]) -> io::Result { LineWriterShim::new(&mut self.inner).write(buf) } @@ -216,7 +218,7 @@ impl Write for LineWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LineWriter +impl fmt::Debug for LineWriter where W: fmt::Debug, { diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs index 0175d2693e89..f2a55da05b22 100644 --- a/library/std/src/io/buffered/linewritershim.rs +++ b/library/std/src/io/buffered/linewritershim.rs @@ -11,11 +11,11 @@ use crate::sys_common::memchr; /// `BufWriters` to be temporarily given line-buffering logic; this is what /// enables Stdout to be alternately in line-buffered or block-buffered mode. #[derive(Debug)] -pub struct LineWriterShim<'a, W: Write> { +pub struct LineWriterShim<'a, W: ?Sized + Write> { buffer: &'a mut BufWriter, } -impl<'a, W: Write> LineWriterShim<'a, W> { +impl<'a, W: ?Sized + Write> LineWriterShim<'a, W> { pub fn new(buffer: &'a mut BufWriter) -> Self { Self { buffer } } @@ -49,7 +49,7 @@ impl<'a, W: Write> LineWriterShim<'a, W> { } } -impl<'a, W: Write> Write for LineWriterShim<'a, W> { +impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> { /// Write some data into this BufReader with line buffering. This means /// that, if any newlines are present in the data, the data up to the last /// newline is sent directly to the underlying writer, and data after it diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 1d9d93f5b64e..420fc4007050 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -86,7 +86,7 @@ impl BufferedCopySpec for W { } } -impl BufferedCopySpec for BufWriter { +impl BufferedCopySpec for BufWriter { fn copy_to(reader: &mut R, writer: &mut Self) -> Result { if writer.capacity() < DEFAULT_BUF_SIZE { return stack_buffer_copy(reader, writer); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8a007d095d5e..173233d7150b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2754,7 +2754,7 @@ trait SizeHint { } } -impl SizeHint for T { +impl SizeHint for T { #[inline] default fn lower_bound(&self) -> usize { 0 diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d53f1a2b2fff..da08c018d0e3 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -188,6 +188,13 @@ //! [array]: prim@array //! [slice]: prim@slice +// To run std tests without x.py without ending up with two copies of std, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. +#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] +// #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] #![doc( @@ -202,12 +209,6 @@ no_global_oom_handling, not(no_global_oom_handling) ))] -// To run std tests without x.py without ending up with two copies of std, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. -#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 7565fbc0d099..814f1c7c2838 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -17,6 +17,7 @@ mod libc { pub use libc::c_int; pub struct ucred; pub struct cmsghdr; + pub struct sockcred2; pub type pid_t = i32; pub type gid_t = u32; pub type uid_t = u32; diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 16c8e0c0ebfc..7d49bbdcbe06 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -466,7 +466,7 @@ impl CopyRead for Take { } } -impl CopyRead for BufReader { +impl CopyRead for BufReader { fn drain_to(&mut self, writer: &mut W, outer_limit: u64) -> Result { let buf = self.buffer(); let buf = &buf[0..min(buf.len(), outer_limit.try_into().unwrap_or(usize::MAX))]; @@ -495,7 +495,7 @@ impl CopyRead for BufReader { } } -impl CopyWrite for BufWriter { +impl CopyWrite for BufWriter { fn properties(&self) -> CopyParams { self.get_ref().properties() } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 878af5088d9f..010015667f7a 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -344,6 +344,29 @@ pub fn available_parallelism() -> io::Result { } } + #[cfg(target_os = "netbsd")] + { + unsafe { + let set = libc::_cpuset_create(); + if !set.is_null() { + let mut count: usize = 0; + if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 { + for i in 0..u64::MAX { + match libc::_cpuset_isset(i, set) { + -1 => break, + 0 => continue, + _ => count = count + 1, + } + } + } + libc::_cpuset_destroy(set); + if let Some(count) = NonZeroUsize::new(count) { + return Ok(count); + } + } + } + } + let mut cpus: libc::c_uint = 0; let mut cpus_size = crate::mem::size_of_val(&cpus); diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 515890aef8df..85a9a5d33752 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -45,6 +45,9 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ # Build both public and internal documentation. + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library && \ + mkdir -p /checkout/obj/staging/doc && \ + cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 19ead2f1b111..efffc3822426 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -34,6 +34,8 @@ x--expand-yaml-anchors--remove: - &shared-ci-variables CI_JOB_NAME: ${{ matrix.name }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - &public-variables SCCACHE_BUCKET: rust-lang-ci-sccache2 @@ -229,6 +231,20 @@ x--expand-yaml-anchors--remove: TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} <<: *step + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + <<: *step + + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + # name is set in previous step + name: ${{ env.DOC_ARTIFACT_NAME }} + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + <<: *step + - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: diff --git a/src/ci/scripts/create-doc-artifacts.sh b/src/ci/scripts/create-doc-artifacts.sh new file mode 100755 index 000000000000..2516b0d85059 --- /dev/null +++ b/src/ci/scripts/create-doc-artifacts.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Compress doc artifacts and name them based on the commit, or the date if +# commit is not available. + +set -euox pipefail + +# Try to get short commit hash, fallback to date +if [ -n "$HEAD_SHA" ]; then + short_rev=$(echo "${HEAD_SHA}" | cut -c1-8) +else + short_rev=$(git rev-parse --short HEAD || date -u +'%Y-%m-%dT%H%M%SZ') +fi + +# Try to get branch, fallback to none +branch=$(git branch --show-current || echo) + +if [ -n "$branch" ]; then + branch="${branch}-" +fi + +if [ "${GITHUB_EVENT_NAME:=none}" = "pull_request" ]; then + pr_num=$(echo "$GITHUB_REF_NAME" | cut -d'/' -f1) + name="doc-${pr_num}-${short_rev}" +else + name="doc-${branch}${short_rev}" +fi + + +if [ -d "obj/staging/doc" ]; then + mkdir -p obj/artifacts/doc + + # Level 12 seems to give a good tradeoff of time vs. space savings + ZSTD_CLEVEL=12 ZSTD_NBTHREADS=4 \ + tar --zstd -cf "obj/artifacts/doc/${name}.tar.zst" -C obj/staging/doc . + + ls -lh obj/artifacts/doc +fi + +# Set this environment variable for future use if running in CI +if [ -n "$GITHUB_ENV" ]; then + echo "DOC_ARTIFACT_NAME=${name}" >> "$GITHUB_ENV" +fi diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0c7950bfd3dd..9f698a3b6bf9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2052,6 +2052,11 @@ pub(crate) fn clean_middle_ty<'tcx>( })) } + ty::Alias(ty::Weak, data) => { + let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs); + clean_middle_ty(bound_ty.rebind(ty), cx, None, None) + } + ty::Param(ref p) => { if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { ImplTrait(bounds) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5bd9389a400a..322ab7a4af3f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -800,10 +800,11 @@ fn assoc_type( if !bounds.is_empty() { write!(w, ": {}", print_generic_bounds(bounds, cx)) } - write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); + // Render the default before the where-clause which aligns with the new recommended style. See #89122. if let Some(default) = default { write!(w, " = {}", default.print(cx)) } + write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); } fn assoc_method( diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 054cfe7597ea..b487cfa5c255 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -213,7 +213,7 @@ a.anchor, h1 a, .search-results a, .stab, -.result-name .primitive > i, .result-name .keyword > i { +.result-name i { color: var(--main-color); } @@ -887,7 +887,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ .search-results .result-name span.alias { color: var(--search-results-alias-color); } -.search-results .result-name span.grey { +.search-results .result-name .grey { color: var(--search-results-grey-color); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 25259971eff2..e724bf1601aa 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -35,6 +35,35 @@ const itemTypes = [ "traitalias", ]; +const longItemTypes = [ + "module", + "extern crate", + "re-export", + "struct", + "enum", + "function", + "type alias", + "static", + "trait", + "", + "trait method", + "method", + "struct field", + "enum variant", + "macro", + "primitive type", + "associated type", + "constant", + "associated constant", + "union", + "foreign type", + "keyword", + "existential type", + "attribute macro", + "derive macro", + "trait alias", +]; + // used for special search precedence const TY_PRIMITIVE = itemTypes.indexOf("primitive"); const TY_KEYWORD = itemTypes.indexOf("keyword"); @@ -1966,16 +1995,11 @@ function initSearch(rawSearchIndex) { array.forEach(item => { const name = item.name; const type = itemTypes[item.ty]; + const longType = longItemTypes[item.ty]; + const typeName = longType.length !== 0 ? `${longType}` : "?"; length += 1; - let extra = ""; - if (type === "primitive") { - extra = " (primitive type)"; - } else if (type === "keyword") { - extra = " (keyword)"; - } - const link = document.createElement("a"); link.className = "result-" + type; link.href = item.href; @@ -1993,13 +2017,14 @@ function initSearch(rawSearchIndex) { alias.insertAdjacentHTML( "beforeend", - " - see "); + " - see "); resultName.appendChild(alias); } + resultName.insertAdjacentHTML( "beforeend", - item.displayPath + "" + name + extra + ""); + `${typeName} ${item.displayPath}${name}`); link.appendChild(resultName); const description = document.createElement("div"); diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index a1d2147cb496..dbaf6aaa853c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1424,6 +1424,7 @@ fn ty_auto_deref_stability<'tcx>( continue; }, ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty), + ty::Alias(ty::Weak, _) => unreachable!("should have been normalized away above"), ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"), ty::Alias(ty::Projection, _) if ty.has_non_region_param() => { TyPosition::new_deref_stable_for_result(precedence, ty) diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed index d18f93875658..204019130ede 100644 --- a/src/tools/clippy/tests/ui/from_over_into.fixed +++ b/src/tools/clippy/tests/ui/from_over_into.fixed @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs index de8ff0b06bdc..46e02847e308 100644 --- a/src/tools/clippy/tests/ui/from_over_into.rs +++ b/src/tools/clippy/tests/ui/from_over_into.rs @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs index 3b280b7488ae..bd62c655216e 100644 --- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs +++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs @@ -32,4 +32,10 @@ impl Into for ContainsVal { } } +type Opaque = impl Sized; +struct IntoOpaque; +impl Into for IntoOpaque { + fn into(self) -> Opaque {} +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr index 251f1d84e74e..bb966af4b0ff 100644 --- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr +++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr @@ -1,29 +1,12 @@ -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:11:1 +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/from_over_into_unfixable.rs:35:15 | -LL | impl Into for String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Opaque = impl Sized; + | ^^^^^^^^^^ | - = help: replace the `Into` implementation with `From` - = note: `-D clippy::from-over-into` implied by `-D warnings` + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:19:1 - | -LL | impl Into for &'static [u8] { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace the `Into` implementation with `From<&'static [u8]>` - -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:28:1 - | -LL | impl Into for ContainsVal { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `impl From for Foreign` is allowed by the orphan rules, for more information see - https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence - = help: replace the `Into` implementation with `From` - -error: aborting due to 3 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs index a2a30c8b931c..4eff62b85ff6 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.rs +++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs @@ -401,25 +401,3 @@ mod issue7344 { } } } - -mod issue10041 { - struct Bomb; - - impl Bomb { - // Hidden default generic parameter. - pub fn new() -> impl PartialOrd { - 0i32 - } - } - - // TAIT with self-referencing bounds - type X = impl std::ops::Add; - - struct Bomb2; - - impl Bomb2 { - pub fn new() -> X { - 0i32 - } - } -} diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr index 2eaebfb5cac5..2b053b462b16 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr +++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr @@ -92,21 +92,5 @@ LL | | unimplemented!() LL | | } | |_________^ -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:410:9 - | -LL | / pub fn new() -> impl PartialOrd { -LL | | 0i32 -LL | | } - | |_________^ - -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:421:9 - | -LL | / pub fn new() -> X { -LL | | 0i32 -LL | | } - | |_________^ - -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs new file mode 100644 index 000000000000..7bc6fec10ba6 --- /dev/null +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![warn(clippy::new_ret_no_self)] + +mod issue10041 { + struct Bomb; + + impl Bomb { + // Hidden default generic parameter. + pub fn new() -> impl PartialOrd { + 0i32 + } + } + + // TAIT with self-referencing bounds + type X = impl std::ops::Add; + + struct Bomb2; + + impl Bomb2 { + pub fn new() -> X { + 0i32 + } + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr new file mode 100644 index 000000000000..babb634fdcd1 --- /dev/null +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Output == issue10041::X` + --> $DIR/new_ret_no_self_overflow.rs:20:25 + | +LL | pub fn new() -> X { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 4b6de3601cab..aa382960891c 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c84d5e7078435a0ddd8770c3530fe7fdbf026ec4 +7513407ac8e673f536d34743fe393bd8b7c45441 diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs index b9199cff079e..bd6cd69215ae 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.rs +++ b/src/tools/miri/tests/fail/terminate-terminator.rs @@ -1,4 +1,4 @@ -//@compile-flags: -Zmir-opt-level=3 +//@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000 // Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated // instead of just `UnwindAction::Terminate`. diff --git a/tests/codegen/enum-debug-niche-2.rs b/tests/codegen/enum-debug-niche-2.rs index 9c72ad9d248a..4b607d505745 100644 --- a/tests/codegen/enum-debug-niche-2.rs +++ b/tests/codegen/enum-debug-niche-2.rs @@ -7,8 +7,8 @@ // compile-flags: -g -C no-prepopulate-passes // CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}} -// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i64 4294967295{{[,)].*}} -// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i64 0{{[,)].*}} +// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i128 4294967295{{[,)].*}} +// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}} #![feature(never_type)] diff --git a/tests/codegen/enum-u128.rs b/tests/codegen/enum-u128.rs new file mode 100644 index 000000000000..f50d360ac9f3 --- /dev/null +++ b/tests/codegen/enum-u128.rs @@ -0,0 +1,27 @@ +// This tests that debug info for "c-like" 128bit enums is properly emitted. +// This is ignored for the fallback mode on MSVC due to problems with PDB. + +// +// ignore-msvc + +// compile-flags: -g -C no-prepopulate-passes + +// CHECK-LABEL: @main +// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "Foo",{{.*}}flags: DIFlagEnumClass,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Lo",{{.*}}value: 0,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}} + +#![allow(incomplete_features)] +#![feature(repr128)] + +#[repr(u128)] +pub enum Foo { + Lo, + Hi = 1 << 64, + Bar = 18_446_745_000_000_000_123, +} + +pub fn main() { + let foo = Foo::Bar; +} diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs index a977ebf1bb7b..573ae1ba68d4 100644 --- a/tests/mir-opt/inline/asm_unwind.rs +++ b/tests/mir-opt/inline/asm_unwind.rs @@ -2,6 +2,7 @@ // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // needs-asm-support +// compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(asm_unwind)] struct D; @@ -10,7 +11,7 @@ impl Drop for D { fn drop(&mut self) {} } -#[inline(always)] +#[inline] fn foo() { let _d = D; unsafe { std::arch::asm!("", options(may_unwind)) }; diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index af2ca895cc63..1b74d818451e 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -1,4 +1,5 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 // EMIT_MIR cycle.f.Inline.diff #[inline(always)] diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs index febf1a8a6bf5..e01c4c1dd021 100644 --- a/tests/mir-opt/inline/inline_diverging.rs +++ b/tests/mir-opt/inline/inline_diverging.rs @@ -1,6 +1,7 @@ // Tests inlining of diverging calls. // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 #![crate_type = "lib"] // EMIT_MIR inline_diverging.f.Inline.diff diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index fa48c56d185d..e05c605a4e47 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -4,30 +4,30 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; - let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; + let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -39,18 +39,18 @@ - } - - bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; ++ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind unreachable]; +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind unreachable]; - } - - bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _3 }; ++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; +- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb2, 1: bb6, 3: bb7, otherwise: bb8]; } @@ -82,7 +82,7 @@ + + bb5: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_9)) = 3; + goto -> bb1; + } @@ -95,7 +95,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_10)) = 1; + goto -> bb1; + } diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 63f70ccc3b52..588f04048d67 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -4,30 +4,30 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; - let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; + let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -39,18 +39,18 @@ - } - - bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; ++ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind: bb4]; - } - - bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _3 }; ++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; +- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } @@ -87,7 +87,7 @@ + + bb6: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_9)) = 3; + goto -> bb1; + } @@ -100,7 +100,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_10)) = 1; + goto -> bb1; + } diff --git a/tests/mir-opt/inline/inline_generator.rs b/tests/mir-opt/inline/inline_generator.rs index 61f1da897bd1..2d71458c1741 100644 --- a/tests/mir-opt/inline/inline_generator.rs +++ b/tests/mir-opt/inline/inline_generator.rs @@ -1,4 +1,5 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(generators, generator_trait)] use std::ops::Generator; @@ -9,8 +10,8 @@ fn main() { let _r = Pin::new(&mut g()).resume(false); } -#[inline(always)] +#[inline] pub fn g() -> impl Generator { - #[inline(always)] + #[inline] |a| { yield if a { 7 } else { 13 } } } diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff index b186a701f65b..f3a6923415a1 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff @@ -18,6 +18,99 @@ + let mut _6: *mut u8; + let mut _7: *const std::vec::Vec; + scope 4 { ++ scope 5 (inlined alloc::alloc::exchange_malloc) { ++ debug size => _4; ++ debug align => _5; ++ let _8: std::alloc::Layout; ++ let mut _9: std::result::Result, std::alloc::AllocError>; ++ let mut _10: isize; ++ let mut _12: !; ++ scope 6 { ++ debug layout => _8; ++ let _11: std::ptr::NonNull<[u8]>; ++ let mut _13: &std::alloc::Global; ++ scope 8 { ++ debug ptr => _11; ++ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { ++ debug self => _11; ++ let mut _15: std::ptr::NonNull; ++ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { ++ debug self => _11; ++ let mut _16: *mut u8; ++ let mut _17: *mut [u8]; ++ scope 20 { ++ scope 21 (inlined NonNull::<[u8]>::as_ptr) { ++ debug self => _11; ++ let mut _18: *const [u8]; ++ } ++ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { ++ debug self => _17; ++ } ++ scope 23 (inlined NonNull::::new_unchecked) { ++ debug ptr => _16; ++ let mut _19: *const u8; ++ scope 24 { ++ scope 25 (inlined NonNull::::new_unchecked::runtime::) { ++ debug ptr => _16; ++ scope 26 (inlined ptr::mut_ptr::::is_null) { ++ debug self => _16; ++ let mut _20: *mut u8; ++ scope 27 { ++ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { ++ debug ptr => _20; ++ scope 29 (inlined ptr::mut_ptr::::addr) { ++ debug self => _20; ++ scope 30 { ++ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { ++ debug self => _20; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ scope 32 (inlined NonNull::::as_ptr) { ++ debug self => _15; ++ let mut _21: *const u8; ++ } ++ } ++ } ++ scope 17 (inlined ::allocate) { ++ debug self => const _; ++ debug layout => _8; ++ } ++ } ++ scope 7 { ++ scope 9 (inlined Layout::from_size_align_unchecked) { ++ debug size => _4; ++ debug align => _5; ++ let mut _14: std::ptr::Alignment; ++ scope 10 { ++ scope 11 (inlined std::ptr::Alignment::new_unchecked) { ++ debug align => _5; ++ scope 12 { ++ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { ++ debug align => _5; ++ scope 15 (inlined core::num::::is_power_of_two) { ++ debug self => _5; ++ scope 16 (inlined core::num::::count_ones) { ++ debug self => _5; ++ } ++ } ++ } ++ } ++ scope 13 { ++ } ++ } ++ } ++ } ++ } ++ } + } + } @@ -31,7 +124,17 @@ + StorageDead(_3); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); -+ _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> [return: bb2, unwind unreachable]; ++ StorageLive(_8); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = _5 as std::ptr::Alignment (Transmute); ++ _8 = Layout { size: _4, align: move _14 }; ++ StorageDead(_14); ++ StorageLive(_9); ++ _13 = const _; ++ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb5, unwind unreachable]; } bb1: { @@ -41,18 +144,56 @@ } bb2: { ++ _12 = handle_alloc_error(_8) -> unwind unreachable; ++ } ++ ++ bb3: { ++ unreachable; ++ } ++ ++ bb4: { ++ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); ++ StorageLive(_15); ++ StorageLive(_16); ++ StorageLive(_17); ++ StorageLive(_18); ++ _18 = (_11.0: *const [u8]); ++ _17 = move _18 as *mut [u8] (PtrToPtr); ++ StorageDead(_18); ++ _16 = _17 as *mut u8 (PtrToPtr); ++ StorageDead(_17); ++ StorageLive(_19); ++ StorageLive(_20); ++ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _15 = NonNull:: { pointer: _19 }; ++ StorageDead(_20); ++ StorageDead(_19); ++ StorageDead(_16); ++ StorageLive(_21); ++ _21 = (_15.0: *const u8); ++ _6 = move _21 as *mut u8 (PtrToPtr); ++ StorageDead(_21); ++ StorageDead(_15); ++ StorageDead(_9); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; -- } -- ++ drop(_1) -> [return: bb1, unwind unreachable]; + } + - bb3: { - StorageDead(_1); - return; -+ drop(_1) -> [return: bb1, unwind unreachable]; ++ bb5: { ++ _10 = discriminant(_9); ++ switchInt(move _10) -> [0: bb4, 1: bb2, otherwise: bb3]; } } diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index a789f9933b4b..4615a3f98267 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -18,6 +18,99 @@ + let mut _6: *mut u8; + let mut _7: *const std::vec::Vec; + scope 4 { ++ scope 5 (inlined alloc::alloc::exchange_malloc) { ++ debug size => _4; ++ debug align => _5; ++ let _8: std::alloc::Layout; ++ let mut _9: std::result::Result, std::alloc::AllocError>; ++ let mut _10: isize; ++ let mut _12: !; ++ scope 6 { ++ debug layout => _8; ++ let _11: std::ptr::NonNull<[u8]>; ++ let mut _13: &std::alloc::Global; ++ scope 8 { ++ debug ptr => _11; ++ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { ++ debug self => _11; ++ let mut _15: std::ptr::NonNull; ++ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { ++ debug self => _11; ++ let mut _16: *mut u8; ++ let mut _17: *mut [u8]; ++ scope 20 { ++ scope 21 (inlined NonNull::<[u8]>::as_ptr) { ++ debug self => _11; ++ let mut _18: *const [u8]; ++ } ++ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { ++ debug self => _17; ++ } ++ scope 23 (inlined NonNull::::new_unchecked) { ++ debug ptr => _16; ++ let mut _19: *const u8; ++ scope 24 { ++ scope 25 (inlined NonNull::::new_unchecked::runtime::) { ++ debug ptr => _16; ++ scope 26 (inlined ptr::mut_ptr::::is_null) { ++ debug self => _16; ++ let mut _20: *mut u8; ++ scope 27 { ++ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { ++ debug ptr => _20; ++ scope 29 (inlined ptr::mut_ptr::::addr) { ++ debug self => _20; ++ scope 30 { ++ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { ++ debug self => _20; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ scope 32 (inlined NonNull::::as_ptr) { ++ debug self => _15; ++ let mut _21: *const u8; ++ } ++ } ++ } ++ scope 17 (inlined ::allocate) { ++ debug self => const _; ++ debug layout => _8; ++ } ++ } ++ scope 7 { ++ scope 9 (inlined Layout::from_size_align_unchecked) { ++ debug size => _4; ++ debug align => _5; ++ let mut _14: std::ptr::Alignment; ++ scope 10 { ++ scope 11 (inlined std::ptr::Alignment::new_unchecked) { ++ debug align => _5; ++ scope 12 { ++ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { ++ debug align => _5; ++ scope 15 (inlined core::num::::is_power_of_two) { ++ debug self => _5; ++ scope 16 (inlined core::num::::count_ones) { ++ debug self => _5; ++ } ++ } ++ } ++ } ++ scope 13 { ++ } ++ } ++ } ++ } ++ } ++ } + } + } @@ -31,7 +124,17 @@ + StorageDead(_3); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); -+ _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> [return: bb3, unwind: bb4]; ++ StorageLive(_8); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = _5 as std::ptr::Alignment (Transmute); ++ _8 = Layout { size: _4, align: move _14 }; ++ StorageDead(_14); ++ StorageLive(_9); ++ _13 = const _; ++ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb7, unwind: bb3]; } bb1: { @@ -48,20 +151,62 @@ + resume; } - bb3: { +- bb3: { - StorageDead(_1); - return; ++ bb3 (cleanup): { ++ drop(_2) -> [return: bb2, unwind terminate]; + } + +- bb4 (cleanup): { +- resume; ++ bb4: { ++ _12 = handle_alloc_error(_8) -> bb3; ++ } ++ ++ bb5: { ++ unreachable; ++ } ++ ++ bb6: { ++ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); ++ StorageLive(_15); ++ StorageLive(_16); ++ StorageLive(_17); ++ StorageLive(_18); ++ _18 = (_11.0: *const [u8]); ++ _17 = move _18 as *mut [u8] (PtrToPtr); ++ StorageDead(_18); ++ _16 = _17 as *mut u8 (PtrToPtr); ++ StorageDead(_17); ++ StorageLive(_19); ++ StorageLive(_20); ++ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _15 = NonNull:: { pointer: _19 }; ++ StorageDead(_20); ++ StorageDead(_19); ++ StorageDead(_16); ++ StorageLive(_21); ++ _21 = (_15.0: *const u8); ++ _6 = move _21 as *mut u8 (PtrToPtr); ++ StorageDead(_21); ++ StorageDead(_15); ++ StorageDead(_9); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; - } - - bb4 (cleanup): { -- resume; -+ drop(_2) -> [return: bb2, unwind terminate]; ++ } ++ ++ bb7: { ++ _10 = discriminant(_9); ++ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; } } diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs index bc578ec90e84..56f174e515b3 100644 --- a/tests/mir-opt/inline/inline_into_box_place.rs +++ b/tests/mir-opt/inline/inline_into_box_place.rs @@ -1,7 +1,7 @@ // ignore-endian-big // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug MIR alignment checks in std alter the diff, breaking the test -// compile-flags: -Z mir-opt-level=4 +// compile-flags: -Zmir-opt-level=4 -Zinline-mir-hint-threshold=200 // EMIT_MIR inline_into_box_place.main.Inline.diff fn main() { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 890d9b109fb4..093925b8e4fa 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -7,129 +7,19 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shl) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: u16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shl::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for u16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: u16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: u16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 65535_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as u16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: u16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: u16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 118e601b136c..50934e0439a3 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -7,129 +7,19 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shl) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: u16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shl::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for u16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: u16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: u16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 65535_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as u16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: u16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: u16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir index 0d692251051e..46f3511b14ca 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir @@ -4,121 +4,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; - scope 1 (inlined core::num::::unchecked_shl) { - debug self => _1; - debug rhs => _2; - let mut _11: u16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shl::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for u16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: u16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: u16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 65535_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shl(_1, _2) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_5); - _5 = _2 as u16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: u16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: u16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shl::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir index 0d692251051e..35fee449c35c 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir @@ -4,121 +4,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; - scope 1 (inlined core::num::::unchecked_shl) { - debug self => _1; - debug rhs => _2; - let mut _11: u16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shl::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for u16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: u16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: u16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 65535_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shl(_1, _2) -> bb1; } bb1: { - StorageLive(_5); - _5 = _2 as u16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: u16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: u16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shl::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff index 61155f5078ff..1659a51b090d 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff @@ -7,129 +7,19 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shr) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: i16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shr::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for i16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: i16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: i16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 32767_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as i16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: i16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: i16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff index 181a423164b2..cb5ec37feb36 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff @@ -7,129 +7,19 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shr) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: i16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shr::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for i16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: i16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: i16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 32767_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as i16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: i16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: i16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir index 66936df380bc..9f2f40002a32 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir @@ -4,121 +4,12 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; - scope 1 (inlined core::num::::unchecked_shr) { - debug self => _1; - debug rhs => _2; - let mut _11: i16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shr::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for i16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: i16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: i16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 32767_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shr(_1, _2) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_5); - _5 = _2 as i16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: i16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: i16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shr::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir index 66936df380bc..aaf3bb62e8a3 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir @@ -4,121 +4,12 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; - scope 1 (inlined core::num::::unchecked_shr) { - debug self => _1; - debug rhs => _2; - let mut _11: i16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shr::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for i16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: i16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: i16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 32767_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shr(_1, _2) -> bb1; } bb1: { - StorageLive(_5); - _5 = _2 as i16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: i16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: i16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shr::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml index c5c386ce750c..6ea6d53e2875 100644 --- a/tests/rustdoc-gui/search-reexport.goml +++ b/tests/rustdoc-gui/search-reexport.goml @@ -14,7 +14,7 @@ assert-attribute: ( "//a[@class='result-import']", {"href": "../test_docs/index.html#reexport.TheStdReexport"}, ) -assert-text: ("//a[@class='result-import']", "test_docs::TheStdReexport") +assert-text: ("a.result-import .result-name", "re-export test_docs::TheStdReexport") click: "//a[@class='result-import']" // We check that it has the background modified thanks to the focus. wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "#494a3d"}) @@ -25,8 +25,8 @@ press-key: 'Enter' write: (".search-input", "AliasForTheStdReexport") wait-for: "//a[@class='result-import']" assert-text: ( - "//a[@class='result-import']", - "AliasForTheStdReexport - see test_docs::TheStdReexport", + "a.result-import .result-name", + "AliasForTheStdReexport - see re-export test_docs::TheStdReexport", ) // Same thing again, we click on it to ensure the background is once again set as expected. click: "//a[@class='result-import']" diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 90f7160b7249..c75e4141434e 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -65,12 +65,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -// Checking the color of "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#788797"}, -) - store-value: (entry_color, "#0096cf") // color of the search entry store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color @@ -182,12 +176,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -// Checking the color for "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#ddd"}, -) - store-value: (entry_color, "#ddd") // color of the search entry store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color @@ -284,12 +272,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -// Checking the color for "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#000"}, -) - store-value: (entry_color, "#000") // color of the search entry store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml index bf096f62c483..afb3a44be303 100644 --- a/tests/rustdoc-gui/search-result-display.goml +++ b/tests/rustdoc-gui/search-result-display.goml @@ -7,11 +7,11 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-css: (".search-results div.desc", {"width": "310px"}) +assert-size: (".search-results div.desc", {"width": 310}) set-window-size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. -assert-css: (".search-results div.desc", {"width": "566px"}) +assert-size: (".search-results div.desc", {"width": 566}) // The result set is all on one line. assert-css: (".search-results .result-name > span", {"display": "inline"}) diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml index 5d56e9d9cd42..1b2be6d4e3e2 100644 --- a/tests/rustdoc-gui/search-result-keyword.goml +++ b/tests/rustdoc-gui/search-result-keyword.goml @@ -5,9 +5,4 @@ write: (".search-input", "CookieMonster") press-key: 'Enter' // Waiting for the search results to appear... wait-for: "#search-tabs" -// Note: The two next assert commands could be merged as one but readability would be -// less good. -// -// Checking that the CSS is displaying " (keyword)" in italic. -assert-text: (".result-name span.keyword > i", "(keyword)") -assert-text: (".result-name span.keyword", "CookieMonster (keyword)") +assert-text: (".result-keyword .result-name", "keyword CookieMonster") diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs index 7ab82bb58296..605176e5feaf 100644 --- a/tests/rustdoc/generic-associated-types/gats.rs +++ b/tests/rustdoc/generic-associated-types/gats.rs @@ -23,9 +23,9 @@ impl LendingIterator for () { pub struct Infinite(T); // @has foo/trait.LendingIterator.html -// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" +// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> = &'a T where Self: 'a" impl LendingIterator for Infinite { - type Item<'a> where Self: 'a = &'a T; + type Item<'a> = &'a T where Self: 'a; fn next<'a>(&'a self) -> Self::Item<'a> { &self.0 diff --git a/tests/ui/impl-trait/nested-return-type2-tait.stderr b/tests/ui/impl-trait/nested-return-type2-tait.stderr index a8eb69cfcb73..4383e8ab3a0c 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait.stderr @@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait { | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/nested-return-type3-tait.stderr b/tests/ui/impl-trait/nested-return-type3-tait.stderr index 5f58c8dca4ad..d32944a0d721 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait.stderr @@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait { | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.stderr b/tests/ui/impl-trait/nested-return-type3-tait2.stderr index c07f6ead7502..a2eddd116653 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait2.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait2.stderr @@ -8,10 +8,6 @@ LL | type Traitable = impl Trait; | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs index af9dfe25bb4c..01c933473ea7 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -1,5 +1,7 @@ #![feature(type_alias_impl_trait)] +// check-pass + type Foo = impl PartialEq<(Foo, i32)>; struct Bar; @@ -11,7 +13,6 @@ impl PartialEq<(Foo, i32)> for Bar { } fn foo() -> Foo { - //~^ ERROR can't compare `Bar` with `(Bar, i32)` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr deleted file mode 100644 index 7b63a3d0b9f1..000000000000 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: can't compare `Bar` with `(Bar, i32)` - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13 - | -LL | fn foo() -> Foo { - | ^^^ no implementation for `Bar == (Bar, i32)` -LL | -LL | Bar - | --- return type was inferred to be `Bar` here - | - = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` - = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index fe62a8f32888..bbd60d4398b7 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -20,6 +20,11 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { | = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9 + | +LL | fn eq(&self, _other: &(Foo, i32)) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs index ad0a003e8794..aab10be2de27 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] type Foo = impl PartialEq<(Foo, i32)>; @@ -13,6 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar { } fn foo() -> Foo { + //~^ ERROR can't compare `Bar` with `(Foo, i32)` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr new file mode 100644 index 000000000000..b98b859a99bf --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `Bar` with `(Foo, i32)` + --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13 + | +LL | fn foo() -> Foo { + | ^^^ no implementation for `Bar == (Foo, i32)` +LL | +LL | Bar + | --- return type was inferred to be `Bar` here + | + = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar` + = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs index 691047c8a405..f30377d6c16e 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.rs +++ b/tests/ui/lint/lint-ctypes-73249-2.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Baz {} +trait Baz {} impl Baz for () {} @@ -9,7 +9,7 @@ type Qux = impl Baz; fn assign() -> Qux {} -pub trait Foo { +trait Foo { type Assoc: 'static; } @@ -18,12 +18,12 @@ impl Foo for () { } #[repr(transparent)] -pub struct A { +struct A { x: &'static ::Assoc, } extern "C" { - pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` + fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr index 8073c33dd463..49fa54114b21 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.stderr +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `Qux`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-2.rs:26:25 + --> $DIR/lint-ctypes-73249-2.rs:26:21 | -LL | pub fn lint_me() -> A<()>; - | ^^^^^ not FFI-safe +LL | fn lint_me() -> A<()>; + | ^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs index 145ba784f7c6..fc11f23a1049 100644 --- a/tests/ui/lint/lint-ctypes-73251-1.rs +++ b/tests/ui/lint/lint-ctypes-73251-1.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Baz {} +trait Baz {} impl Baz for u32 {} type Qux = impl Baz; -pub trait Foo { +trait Foo { type Assoc; } @@ -20,7 +20,7 @@ fn assign() -> Qux { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` + fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr index 9f43576ad735..b4eb921b97e2 100644 --- a/tests/ui/lint/lint-ctypes-73251-1.stderr +++ b/tests/ui/lint/lint-ctypes-73251-1.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `Qux`, which is not FFI-safe - --> $DIR/lint-ctypes-73251-1.rs:23:25 + --> $DIR/lint-ctypes-73251-1.rs:23:21 | -LL | pub fn lint_me() -> ::Assoc; - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs index df71a9457962..fbe0a58f3b5b 100644 --- a/tests/ui/lint/lint-ctypes-73251-2.rs +++ b/tests/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` + fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr index 0b3de379c19d..e44cd45bd30f 100644 --- a/tests/ui/lint/lint-ctypes-73251-2.stderr +++ b/tests/ui/lint/lint-ctypes-73251-2.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `AliasA`, which is not FFI-safe - --> $DIR/lint-ctypes-73251-2.rs:36:25 + --> $DIR/lint-ctypes-73251-2.rs:36:21 | -LL | pub fn lint_me() -> ::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs index ebc2ca77b67a..a00d1a75aec2 100644 --- a/tests/ui/lint/lint-ctypes-73251.rs +++ b/tests/ui/lint/lint-ctypes-73251.rs @@ -3,7 +3,7 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Foo { +trait Foo { type Assoc; } @@ -16,7 +16,7 @@ type Bar = impl Foo; fn assign() -> Bar {} extern "C" { - pub fn lint_me() -> ::Assoc; + fn lint_me() -> ::Assoc; } fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs index b7cc38e99fc3..5faeac9ed4c3 100644 --- a/tests/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs @@ -3,12 +3,12 @@ type A = impl Fn(); -pub fn ret_closure() -> A { +pub(crate) fn ret_closure() -> A { || {} } extern "C" { - pub fn a(_: A); + pub(crate) fn a(_: A); //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes] } diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr index 33aa95854e30..ba9e18bcce5c 100644 --- a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 + --> $DIR/opaque-ty-ffi-unsafe.rs:11:24 | -LL | pub fn a(_: A); - | ^ not FFI-safe +LL | pub(crate) fn a(_: A); + | ^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/mir_alignment_check.rs index 68a5384b30d7..d1bf3d46a7c7 100644 --- a/tests/ui/mir/mir_alignment_check.rs +++ b/tests/ui/mir/mir_alignment_check.rs @@ -1,5 +1,6 @@ // run-fail // ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 // compile-flags: -C debug-assertions // error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs new file mode 100644 index 000000000000..56388c1047e9 --- /dev/null +++ b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs @@ -0,0 +1,21 @@ +// run-pass +// only-i686-pc-windows-msvc +// compile-flags: -Copt-level=0 -Cdebug-assertions=yes + +// MSVC isn't sure if on 32-bit Windows its u64 type is 8-byte-aligned or 4-byte-aligned. +// So this test ensures that on i686-pc-windows-msvc, we do not insert a runtime check +// that will fail on dereferencing of a pointer to u64 which is not 8-byte-aligned but is +// 4-byte-aligned. + +#![feature(strict_provenance)] + +fn main() { + let mut x = [0u64; 2]; + let ptr: *mut u8 = x.as_mut_ptr().cast::(); + unsafe { + let misaligned = ptr.add(4).cast::(); + assert!(misaligned.addr() % 8 != 0); + assert!(misaligned.addr() % 4 == 0); + *misaligned = 42; + } +} diff --git a/tests/ui/parser/lit-err-in-macro.rs b/tests/ui/parser/lit-err-in-macro.rs new file mode 100644 index 000000000000..cff8ee6b40ca --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.rs @@ -0,0 +1,10 @@ +macro_rules! f { + ($abi:literal) => { + extern $abi fn f() {} + } +} + +f!("Foo"__); +//~^ ERROR suffixes on string literals are invalid + +fn main() {} diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr new file mode 100644 index 000000000000..a61fb5c85d49 --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/lit-err-in-macro.rs:7:4 + | +LL | f!("Foo"__); + | ^^^^^^^ invalid suffix `__` + +error: aborting due to previous error + diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs new file mode 100644 index 000000000000..74c7afd6b9ed --- /dev/null +++ b/tests/ui/traits/issue-105231.rs @@ -0,0 +1,9 @@ +//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` +struct A(B); +//~^ ERROR recursive types `A` and `B` have infinite size +struct B(A>); +trait Foo {} +impl Foo for T where T: Send {} +impl Foo for B {} + +fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr new file mode 100644 index 000000000000..fe20c47c57a8 --- /dev/null +++ b/tests/ui/traits/issue-105231.stderr @@ -0,0 +1,29 @@ +error[E0072]: recursive types `A` and `B` have infinite size + --> $DIR/issue-105231.rs:2:1 + | +LL | struct A(B); + | ^^^^^^^^^^^ ---- recursive without indirection +LL | +LL | struct B(A>); + | ^^^^^^^^^^^ ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct A(Box>); +LL | +LL ~ struct B(Box>>); + | + +error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) +note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-105231.rs:4:8 + | +LL | struct B(A>); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0072, E0275. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/new-solver/closure-substs-ambiguity.rs b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs new file mode 100644 index 000000000000..48432f4020f8 --- /dev/null +++ b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs @@ -0,0 +1,7 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn main() { + let mut x: Vec<_> = vec![]; + x.extend(Some(1i32).into_iter().map(|x| x)); +} diff --git a/tests/ui/traits/new-solver/opportunistic-region-resolve.rs b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs new file mode 100644 index 000000000000..2610789cd485 --- /dev/null +++ b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs @@ -0,0 +1,19 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(rustc_attrs)] + +#[rustc_coinductive] +trait Trait {} + +#[rustc_coinductive] +trait Indirect {} +impl Indirect for T {} + +impl<'a> Trait for &'a () where &'a (): Indirect {} + +fn impls_trait() {} + +fn main() { + impls_trait::<&'static ()>(); +} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs index a1584581e6c4..d9f7c7809b98 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs @@ -4,9 +4,9 @@ #![allow(dead_code)] mod m { - type Foo = impl std::fmt::Debug; + pub(crate) type Foo = impl std::fmt::Debug; - pub fn foo() -> Foo { + pub(crate) fn foo() -> Foo { 22_u32 } } diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs new file mode 100644 index 000000000000..5a9e87c09196 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::{Debug, Display}; + +struct Struct(Option); + +// Make sure that, in contrast to type aliases without opaque types, +// we actually do a wf check for the aliased type. +type Foo = (impl Debug, Struct); +//~^ ERROR: `T` doesn't implement `std::fmt::Display` + +fn foo() -> Foo { + (Vec::::new(), Struct(None)) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr new file mode 100644 index 000000000000..a845cba77163 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -0,0 +1,20 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/bounds-are-checked3.rs:9:35 + | +LL | type Foo = (impl Debug, Struct); + | ^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Struct` + --> $DIR/bounds-are-checked3.rs:5:18 + | +LL | struct Struct(Option); + | ^^^^^^^ required by this bound in `Struct` +help: consider further restricting this bound + | +LL | type Foo = (impl Debug, Struct); + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/bounds.rs b/tests/ui/type-alias-impl-trait/bounds.rs new file mode 100644 index 000000000000..dc05b70c5cc9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +use std::fmt::Debug; + +// No need to report the `type_alias_bounds` lint, as +// the moment an opaque type is mentioned, we actually do check +// type alias bounds. +type Foo = (impl Debug, usize); + +fn foo() -> Foo { + (Vec::::new(), 1234) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr index 00b0dbbb583f..c923eb08ab31 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar LL | impl foreign_crate::ForeignTrait for AliasOfForeignType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- | | | - | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | | `AliasOfForeignType` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs index 8b51f55715e9..4d84b2cbbe9a 100644 --- a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs +++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs @@ -11,12 +11,12 @@ type Foo = impl std::fmt::Display; type Bar = impl std::fmt::Display; mod foo { - pub fn foo() -> super::Foo { + pub(crate) fn foo() -> super::Foo { "foo" } - pub mod bar { - pub fn bar() -> crate::Bar { + pub(crate) mod bar { + pub(crate) fn bar() -> crate::Bar { 1 } } diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr index c73288329b01..bc9280127acc 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | fn underconstrain(_: T) -> Underconstrained { | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -note: required by a bound in `Underconstrained` +note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained.rs:6:26 | LL | type Underconstrained = impl Send; - | ^^^^^ required by this bound in `Underconstrained` + | ^^^^^ required by this bound help: consider restricting type parameter `T` | LL | fn underconstrain(_: T) -> Underconstrained { diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index d77d978aa444..fdc9ec090dbe 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -4,11 +4,11 @@ error[E0277]: `U` doesn't implement `Debug` LL | fn underconstrained(_: U) -> Underconstrained { | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | -note: required by a bound in `Underconstrained` +note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 | LL | type Underconstrained = impl Send; - | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained` + | ^^^^^^^^^^^^^^^ required by this bound help: consider restricting type parameter `U` | LL | fn underconstrained(_: U) -> Underconstrained { @@ -20,11 +20,11 @@ error[E0277]: `V` doesn't implement `Debug` LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` | -note: required by a bound in `Underconstrained2` +note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:13:27 | LL | type Underconstrained2 = impl Send; - | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained2` + | ^^^^^^^^^^^^^^^ required by this bound help: consider restricting type parameter `V` | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs new file mode 100644 index 000000000000..00d1a1a226d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +#![feature(auto_traits)] + +type Alias = (impl Sized, u8); + +auto trait Trait {} +impl Trait for Alias {} +//~^ ERROR traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias` + +fn _def() -> Alias { + (42, 42) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr new file mode 100644 index 000000000000..c312ee7dece8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr @@ -0,0 +1,11 @@ +error[E0321]: traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias` + --> $DIR/impl_for_weak_alias.rs:7:1 + | +LL | impl Trait for Alias {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Trait` if and only if `Trait` is one of the trait object's trait bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs index 4a11bb5020e6..b89c3e4590f2 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -1,9 +1,10 @@ #![feature(type_alias_impl_trait)] +// check-pass + type Foo = impl Fn() -> Foo; fn foo() -> Foo { -//~^ ERROR: overflow evaluating the requirement foo } diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr deleted file mode 100644 index 0a34e8486a55..000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Foo: Sized` - --> $DIR/issue-53398-cyclic-types.rs:5:13 - | -LL | fn foo() -> Foo { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) - = note: required because it appears within the type `fn() -> Foo {foo}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/obligation_ice.rs b/tests/ui/type-alias-impl-trait/obligation_ice.rs new file mode 100644 index 000000000000..5aef04ff19c0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/obligation_ice.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +use std::iter::{once, Chain}; + +trait Trait<'a, 'b: 'a> {} + +impl<'a, 'b: 'a, T> Trait<'a, 'b> for std::iter::Cloned {} + +type I<'a, 'b: 'a, A: Trait<'a, 'b>> = Chain>; +fn test2<'a, 'b, A: Trait<'a, 'b> + Iterator>(x: A) -> I<'a, 'b, A> { + x.chain(once("5")) +} + +fn main() { + assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::>()); +} diff --git a/tests/ui/type-alias-impl-trait/privacy.rs b/tests/ui/type-alias-impl-trait/privacy.rs new file mode 100644 index 000000000000..aa092f6f8ecc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/privacy.rs @@ -0,0 +1,8 @@ +#![feature(type_alias_impl_trait)] + +type Foo = (impl Sized, u8); +pub fn foo() -> Foo { + //~^ ERROR private type alias `Foo` in public interface + (42, 42) +} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/privacy.stderr b/tests/ui/type-alias-impl-trait/privacy.stderr new file mode 100644 index 000000000000..e8c6039cdc84 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/privacy.stderr @@ -0,0 +1,11 @@ +error[E0446]: private type alias `Foo` in public interface + --> $DIR/privacy.rs:4:1 + | +LL | type Foo = (impl Sized, u8); + | -------- `Foo` declared as private +LL | pub fn foo() -> Foo { + | ^^^^^^^^^^^^^^^^^^^ can't leak private type alias + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs index d40715717d49..18f09b548675 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -1,9 +1,9 @@ -// run-pass #![feature(type_alias_impl_trait)] type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>` i } diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr new file mode 100644 index 000000000000..4155a114b4f9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `&i32` with `Bar<'a, 'b>` + --> $DIR/self-referential-3.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>` +LL | +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs index 3ff5406a3827..34b7c24df9f6 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.rs +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -10,7 +10,7 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { type Foo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - //~^ ERROR can't compare `&i32` with `(i32, &i32)` + //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` (42, i) } diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr index aff489d70e38..9a17d495b629 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -10,16 +10,16 @@ LL | i = help: the trait `PartialEq>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` -error[E0277]: can't compare `&i32` with `(i32, &i32)` +error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` --> $DIR/self-referential.rs:12:31 | LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == (i32, &i32)` + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})` LL | LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | - = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs index 07c891f0638c..4e7388517a5e 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs @@ -4,20 +4,20 @@ // Regression test for issue #61863 -pub trait MyTrait {} +trait MyTrait {} #[derive(Debug)] -pub struct MyStruct { +struct MyStruct { v: u64, } impl MyTrait for MyStruct {} -pub fn bla() -> TE { +fn bla() -> TE { return MyStruct { v: 1 }; } -pub fn bla2() -> TE { +fn bla2() -> TE { bla() } diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr index e9032433494a..24f5cc8c7339 100644 --- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -25,6 +25,11 @@ LL | fn dont_define_this(_private: Private) {} | ^^^^^^^ = note: expected signature `fn(Private)` found signature `fn(MyPrivate)` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/unnameable_type.rs:20:5 + | +LL | fn dont_define_this(_private: MyPrivate) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors