diff --git a/RELEASES.md b/RELEASES.md index 2297924c7f33..305da6a3550e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -97,7 +97,6 @@ Cargo - [Prevent dashes in `lib.name`, always normalizing to `_`.](https://github.com/rust-lang/cargo/pull/12783/) - [Stabilize MSRV-aware version requirement selection in `cargo add`.](https://github.com/rust-lang/cargo/pull/13608/) - [Switch to using `gitoxide` by default for listing files.](https://github.com/rust-lang/cargo/pull/13696/) -- [Error on `[project]` in Edition 2024; `cargo fix --edition` will change it to `[package]`.](https://github.com/rust-lang/cargo/pull/13747/) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index df1a1411cf5f..9fd23bc94cf6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -8,7 +8,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; use rustc_middle::bug; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast}; use rustc_middle::{ hir::place::PlaceBase, mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location}, @@ -937,56 +937,81 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let node = self.infcx.tcx.hir_node(fn_call_id); let def_id = hir.enclosing_body_owner(fn_call_id); let mut look_at_return = true; - // If we can detect the expression to be an `fn` call where the closure was an argument, - // we point at the `fn` definition argument... - if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(func, args), .. }) = node { - let arg_pos = args + + // If the HIR node is a function or method call gets the def ID + // of the called function or method and the span and args of the call expr + let get_call_details = || { + let hir::Node::Expr(hir::Expr { hir_id, kind, .. }) = node else { + return None; + }; + + let typeck_results = self.infcx.tcx.typeck(def_id); + + match kind { + hir::ExprKind::Call(expr, args) => { + if let Some(ty::FnDef(def_id, _)) = + typeck_results.node_type_opt(expr.hir_id).as_ref().map(|ty| ty.kind()) + { + Some((*def_id, expr.span, *args)) + } else { + None + } + } + hir::ExprKind::MethodCall(_, _, args, span) => { + if let Some(def_id) = typeck_results.type_dependent_def_id(*hir_id) { + Some((def_id, *span, *args)) + } else { + None + } + } + _ => None, + } + }; + + // If we can detect the expression to be an function or method call where the closure was an argument, + // we point at the function or method definition argument... + if let Some((callee_def_id, call_span, call_args)) = get_call_details() { + let arg_pos = call_args .iter() .enumerate() .filter(|(_, arg)| arg.hir_id == closure_id) .map(|(pos, _)| pos) .next(); - let tables = self.infcx.tcx.typeck(def_id); - if let Some(ty::FnDef(def_id, _)) = - tables.node_type_opt(func.hir_id).as_ref().map(|ty| ty.kind()) - { - let arg = match hir.get_if_local(*def_id) { - Some( - hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn(sig, ..), .. + + let arg = match hir.get_if_local(callee_def_id) { + Some( + hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + ident, + kind: hir::TraitItemKind::Fn(sig, _), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + ident, + kind: hir::ImplItemKind::Fn(sig, _), + .. + }), + ) => Some( + arg_pos + .and_then(|pos| { + sig.decl.inputs.get( + pos + if sig.decl.implicit_self.has_implicit_self() { + 1 + } else { + 0 + }, + ) }) - | hir::Node::TraitItem(hir::TraitItem { - ident, - kind: hir::TraitItemKind::Fn(sig, _), - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - ident, - kind: hir::ImplItemKind::Fn(sig, _), - .. - }), - ) => Some( - arg_pos - .and_then(|pos| { - sig.decl.inputs.get( - pos + if sig.decl.implicit_self.has_implicit_self() { - 1 - } else { - 0 - }, - ) - }) - .map(|arg| arg.span) - .unwrap_or(ident.span), - ), - _ => None, - }; - if let Some(span) = arg { - err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); - err.span_label(func.span, "expects `Fn` instead of `FnMut`"); - err.span_label(closure_span, "in this closure"); - look_at_return = false; - } + .map(|arg| arg.span) + .unwrap_or(ident.span), + ), + _ => None, + }; + if let Some(span) = arg { + err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); + err.span_label(call_span, "expects `Fn` instead of `FnMut`"); + err.span_label(closure_span, "in this closure"); + look_at_return = false; } } @@ -1020,7 +1045,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_using_iter_mut(&self, err: &mut Diag<'_>) { let source = self.body.source; let hir = self.infcx.tcx.hir(); - if let InstanceDef::Item(def_id) = source.instance + if let InstanceKind::Item(def_id) = source.instance && let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id) && let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind && let Node::Expr(expr) = self.infcx.tcx.parent_hir_node(*hir_id) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 2cf548e28b18..77fb9fb43151 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -628,9 +628,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | GenericArgKind::Const(_), _, ) => { - // This was previously a `span_delayed_bug` and could be - // reached by the test for #82126, but no longer. - self.dcx().span_bug( + self.dcx().span_delayed_bug( hir_arg.span(), format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index bd5a88769059..695dbaf2804b 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -399,7 +399,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } match instance.def { - InstanceDef::Intrinsic(_) => { + InstanceKind::Intrinsic(_) => { match crate::intrinsics::codegen_intrinsic_call( fx, instance, @@ -412,7 +412,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( Err(instance) => Some(instance), } } - InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => { + InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => { // empty drop glue - a nop. let dest = target.expect("Non terminating drop_in_place_real???"); let ret_block = fx.get_block(dest); @@ -494,7 +494,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let (func_ref, first_arg_override) = match instance { // Trait object call - Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { + Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => { if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); fx.add_comment( @@ -598,7 +598,7 @@ pub(crate) fn codegen_drop<'tcx>( let ty = drop_place.layout().ty; let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx); - if let ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) = + if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) = drop_instance.def { // we don't actually need to drop anything @@ -630,7 +630,7 @@ pub(crate) fn codegen_drop<'tcx>( // FIXME(eddyb) perhaps move some of this logic into // `Instance::resolve_drop_in_place`? let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), + def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0), args: drop_instance.args, }; let fn_abi = @@ -673,7 +673,7 @@ pub(crate) fn codegen_drop<'tcx>( fx.bcx.switch_to_block(continued); let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), + def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0), args: drop_instance.args, }; let fn_abi = @@ -684,7 +684,7 @@ pub(crate) fn codegen_drop<'tcx>( fx.bcx.ins().call_indirect(sig, drop_fn, &[data]); } _ => { - assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); + assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _))); let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty()); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index a53598018f4a..87c5da3b7c3e 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -50,7 +50,7 @@ pub(crate) fn codegen_tls_ref<'tcx>( ) -> CValue<'tcx> { let tls_ptr = if !def_id.is_local() && fx.tcx.needs_thread_local_shim(def_id) { let instance = ty::Instance { - def: ty::InstanceDef::ThreadLocalShim(def_id), + def: ty::InstanceKind::ThreadLocalShim(def_id), args: ty::GenericArgs::empty(), }; let func_ref = fx.get_function_ref(instance); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index cafdc051db5a..b21c559e6686 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1261,7 +1261,7 @@ fn codegen_regular_intrinsic_call<'tcx>( } // Unimplemented intrinsics must have a fallback body. The fallback body is obtained - // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`. + // by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`. _ => { let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap(); if intrinsic.must_be_overridden { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 0fea3fd42539..2edb34e7c20d 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -98,7 +98,7 @@ mod prelude { pub(crate) use rustc_middle::mir::{self, *}; pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; pub(crate) use rustc_middle::ty::{ - self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, UintTy, + self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy, }; pub(crate) use rustc_span::Span; pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT}; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index a6df8950b351..1d61c1564091 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -310,7 +310,7 @@ fn exported_symbols_provider_local( if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() { use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; - use rustc_middle::ty::InstanceDef; + use rustc_middle::ty::InstanceKind; // Normally, we require that shared monomorphizations are not hidden, // because if we want to re-use a monomorphization from a Rust dylib, it @@ -337,7 +337,7 @@ fn exported_symbols_provider_local( } match *mono_item { - MonoItem::Fn(Instance { def: InstanceDef::Item(def), args }) => { + MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => { if args.non_erasable_generics(tcx, def).next().is_some() { let symbol = ExportedSymbol::Generic(def, args); symbols.push(( @@ -350,7 +350,7 @@ fn exported_symbols_provider_local( )); } } - MonoItem::Fn(Instance { def: InstanceDef::DropGlue(def_id, Some(ty)), args }) => { + MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => { // A little sanity-check debug_assert_eq!( args.non_erasable_generics(tcx, def_id).next(), @@ -366,7 +366,7 @@ fn exported_symbols_provider_local( )); } MonoItem::Fn(Instance { - def: InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)), + def: InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty)), args, }) => { // A little sanity-check @@ -556,7 +556,7 @@ pub fn symbol_name_for_instance_in_crate<'tcx>( rustc_symbol_mangling::symbol_name_for_instance_in_crate( tcx, ty::Instance { - def: ty::InstanceDef::ThreadLocalShim(def_id), + def: ty::InstanceKind::ThreadLocalShim(def_id), args: ty::GenericArgs::empty(), }, instantiating_crate, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index bd9704b37aea..57138d3b9dbd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = self.monomorphize(ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); - if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { + if let ty::InstanceKind::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. return helper.funclet_br(self, bx, target, mergeable_succ); } @@ -541,7 +541,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // \-------/ // let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function + def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function args: drop_fn.args, }; debug!("ty = {:?}", ty); @@ -583,7 +583,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // // SO THEN WE CAN USE THE ABOVE CODE. let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function + def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function args: drop_fn.args, }; debug!("ty = {:?}", ty); @@ -855,7 +855,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def = instance.map(|i| i.def); if let Some( - ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None), + ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None), ) = def { // Empty drop glue; a no-op. @@ -871,7 +871,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Handle intrinsics old codegen wants Expr's for, ourselves. let intrinsic = match def { - Some(ty::InstanceDef::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()), + Some(ty::InstanceKind::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()), _ => None, }; @@ -1026,7 +1026,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 'make_args: for (i, arg) in first_args.iter().enumerate() { let mut op = self.codegen_operand(bx, &arg.node); - if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { + if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) { match op.val { Pair(data_ptr, meta) => { // In the case of Rc, we need to explicitly pass a diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index ad6b3f1159de..3dc7dc355115 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -704,7 +704,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id) { let instance = ty::Instance { - def: ty::InstanceDef::ThreadLocalShim(def_id), + def: ty::InstanceKind::ThreadLocalShim(def_id), args: ty::GenericArgs::empty(), }; let fn_ptr = bx.get_fn_addr(instance); diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2dbeb7d5e0ca..cb5aac7e5601 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -399,7 +399,6 @@ const_eval_unwind_past_top = ## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`. ## (We'd love to sort this differently to make that more clear but tidy won't let us...) -const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty} const_eval_validation_const_ref_to_extern = {$front_matter}: encountered reference to `extern` static in `const` @@ -454,7 +453,6 @@ const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected} const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range} -const_eval_validation_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty} const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes}) const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes}) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 0818d9425e20..ab60cc379209 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; -use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt}; +use rustc_middle::ty::{Instance, InstanceKind, TypeVisitableExt}; use rustc_mir_dataflow::Analysis; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; @@ -769,7 +769,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if let Ok(Some(instance)) = Instance::resolve(tcx, param_env, callee, fn_args) - && let InstanceDef::Item(def) = instance.def + && let InstanceKind::Item(def) = instance.def { // Resolve a trait method call to its concrete implementation, which may be in a // `const` trait impl. This is only used for the const stability check below, since diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 4b8145eb4855..c60df06bb0ef 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -289,7 +289,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. - if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { + if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { let ty = key.value.instance.ty(tcx, key.param_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index d3631e0d7232..99276bac0350 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -398,10 +398,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { fn load_mir( ecx: &InterpCx<'tcx, Self>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { match instance { - ty::InstanceDef::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)), + ty::InstanceKind::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)), _ => Ok(ecx.tcx.instance_mir(instance)), } } @@ -424,7 +424,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { }; // Only check non-glue functions - if let ty::InstanceDef::Item(def) = instance.def { + if let ty::InstanceKind::Item(def) = instance.def { // Execution might have wandered off into other crates, so we cannot do a stability- // sensitive check here. But we can at least rule out functions that are not const at // all. That said, we have to allow calling functions inside a trait marked with @@ -540,7 +540,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ); } return Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), + def: ty::InstanceKind::Item(instance.def_id()), args: instance.args, })); } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index e5ea4c3442ea..91d17fdd8959 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -640,9 +640,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { const_eval_validation_ref_to_uninhabited } - PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_static, - PtrToStatic { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_ref_to_static, - PointerAsInt { .. } => const_eval_validation_pointer_as_int, PartialPointer => const_eval_validation_partial_pointer, ConstRefToMutable => const_eval_validation_const_ref_to_mutable, @@ -807,7 +804,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ); } NullPtr { .. } - | PtrToStatic { .. } | ConstRefToMutable | ConstRefToExtern | MutableRefToImmutable diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 4d93038a81e4..86325c5ae240 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -562,7 +562,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn load_mir( &self, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 4ae0aca5a0c0..e91ab7c17916 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -177,7 +177,7 @@ pub trait Machine<'tcx>: Sized { /// constants, ... fn load_mir( ecx: &InterpCx<'tcx, Self>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { Ok(ecx.tcx.instance_mir(instance)) } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 8f76a1486795..74521d0f4934 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -175,7 +175,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Drop { place, target, unwind, replace: _ } => { let place = self.eval_place(place)?; let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty); - if let ty::InstanceDef::DropGlue(_, None) = instance.def { + if let ty::InstanceKind::DropGlue(_, None) = instance.def { // This is the branch we enter if and only if the dropped type has no drop glue // whatsoever. This can happen as a result of monomorphizing a drop of a // generic. In order to make sure that generic and non-generic code behaves @@ -550,7 +550,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; match instance.def { - ty::InstanceDef::Intrinsic(def_id) => { + ty::InstanceKind::Intrinsic(def_id) => { assert!(self.tcx.intrinsic(def_id).is_some()); // FIXME: Should `InPlace` arguments be reset to uninit? if let Some(fallback) = M::call_intrinsic( @@ -562,7 +562,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { unwind, )? { assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden); - assert!(matches!(fallback.def, ty::InstanceDef::Item(_))); + assert!(matches!(fallback.def, ty::InstanceKind::Item(_))); return self.eval_fn_call( FnVal::Instance(fallback), (caller_abi, caller_fn_abi), @@ -576,18 +576,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) } } - ty::InstanceDef::VTableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::CloneShim(..) - | ty::InstanceDef::FnPtrAddrShim(..) - | ty::InstanceDef::ThreadLocalShim(..) - | ty::InstanceDef::AsyncDropGlueCtorShim(..) - | ty::InstanceDef::Item(_) => { + ty::InstanceKind::VTableShim(..) + | ty::InstanceKind::ReifyShim(..) + | ty::InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | ty::InstanceKind::FnPtrShim(..) + | ty::InstanceKind::DropGlue(..) + | ty::InstanceKind::CloneShim(..) + | ty::InstanceKind::FnPtrAddrShim(..) + | ty::InstanceKind::ThreadLocalShim(..) + | ty::InstanceKind::AsyncDropGlueCtorShim(..) + | ty::InstanceKind::Item(_) => { // We need MIR for this fn let Some((body, instance)) = M::find_mir_or_eval_fn( self, @@ -786,9 +786,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) => Ok(()), } } - // `InstanceDef::Virtual` does not have callable MIR. Calls to `Virtual` instances must be + // `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be // codegen'd / interpreted as virtual calls through the vtable. - ty::InstanceDef::Virtual(def_id, idx) => { + ty::InstanceKind::Virtual(def_id, idx) => { let mut args = args.to_vec(); // We have to implement all "object safe receivers". So we have to go search for a // pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively @@ -965,7 +965,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let place = self.force_allocation(place)?; // We behave a bit different from codegen here. - // Codegen creates an `InstanceDef::Virtual` with index 0 (the slot of the drop method) and + // Codegen creates an `InstanceKind::Virtual` with index 0 (the slot of the drop method) and // then dispatches that to the normal call machinery. However, our call machinery currently // only supports calling `VtblEntry::Method`; it would choke on a `MetadataDropInPlace`. So // instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call` diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index f6537ed6ea9e..bbe5e5fe3edb 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -44,7 +44,7 @@ where | ty::CoroutineClosure(def_id, args, ..) | ty::Coroutine(def_id, args, ..) | ty::FnDef(def_id, args) => { - let instance = ty::InstanceDef::Item(def_id); + let instance = ty::InstanceKind::Item(def_id); let unused_params = self.tcx.unused_generic_params(instance); for (index, arg) in args.into_iter().enumerate() { let index = index diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9531c002829e..061afd030623 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -750,16 +750,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. + #[instrument(level = "trace", skip(self), ret)] pub fn resolve_ty_and_res_fully_qualified_call( &self, qpath: &'tcx QPath<'tcx>, hir_id: HirId, span: Span, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { - debug!( - "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", - qpath, hir_id, span - ); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, path) => { return ( @@ -1417,10 +1414,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This also occurs for an enum variant on a type alias. let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args)); let self_ty = self.normalize(span, self_ty); - match self.at(&self.misc(span), self.param_env).eq( + match self.at(&self.misc(span), self.param_env).sub( DefineOpaqueTypes::Yes, - impl_ty, self_ty, + impl_ty, ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d52286d5887d..f881d53858a2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -756,7 +756,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { || tcx.hir().body_const_context(def_id).is_some() { tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); - tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id())); + tcx.ensure().unused_generic_params(ty::InstanceKind::Item(def_id.to_def_id())); } } }); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 043042a492b5..da1f36112ab3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -14,6 +14,7 @@ lint_associated_const_elided_lifetime = {$elided -> *[false] `'_` cannot be used here } .suggestion = use the `'static` lifetime + .note = cannot automatically infer `'static` because of other lifetimes in scope lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 83640d7210fa..290bb5173dbe 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -319,11 +319,20 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnusedQualifications { removal_span } => { lints::UnusedQualifications { removal_span }.decorate_lint(diag); } - BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => { + BuiltinLintDiag::AssociatedConstElidedLifetime { + elided, + span: lt_span, + lifetimes_in_scope, + } => { let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; let code = if elided { "'static " } else { "'static" }; - lints::AssociatedConstElidedLifetime { span: lt_span, code, elided } - .decorate_lint(diag); + lints::AssociatedConstElidedLifetime { + span: lt_span, + code, + elided, + lifetimes_in_scope, + } + .decorate_lint(diag); } BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => { lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 8059f5c1a2ea..f60f8f7c6b7f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2873,6 +2873,8 @@ pub struct AssociatedConstElidedLifetime { pub code: &'static str, pub elided: bool, + #[note] + pub lifetimes_in_scope: MultiSpan, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a12c76037e77..1913b9d6a1c3 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4593,16 +4593,18 @@ declare_lint! { declare_lint! { /// The `elided_lifetimes_in_associated_constant` lint detects elided lifetimes - /// that were erroneously allowed in associated constants. + /// in associated constants when there are other lifetimes in scope. This was + /// accidentally supported, and this lint was later relaxed to allow eliding + /// lifetimes to `'static` when there are no lifetimes in scope. /// /// ### Example /// /// ```rust,compile_fail /// #![deny(elided_lifetimes_in_associated_constant)] /// - /// struct Foo; + /// struct Foo<'a>(&'a ()); /// - /// impl Foo { + /// impl<'a> Foo<'a> { /// const STR: &str = "hello, world"; /// } /// ``` diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 1ce95df34041..70330c445776 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -696,6 +696,7 @@ pub enum BuiltinLintDiag { AssociatedConstElidedLifetime { elided: bool, span: Span, + lifetimes_in_scope: MultiSpan, }, RedundantImportVisibility { span: Span, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 1cef35f082b9..c9450142cd3b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -191,7 +191,7 @@ impl IntoArgs for (CrateNum, DefId) { } } -impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> { +impl<'tcx> IntoArgs for ty::InstanceKind<'tcx> { type Other = (); fn into_args(self) -> (DefId, ()) { (self.def_id(), ()) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d7840a2d516f..4bd2ec09a6e6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1693,7 +1693,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); } - let instance = ty::InstanceDef::Item(def_id.to_def_id()); + let instance = ty::InstanceKind::Item(def_id.to_def_id()); let unused = tcx.unused_generic_params(instance); self.tables.unused_generic_params.set(def_id.local_def_index, unused); } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index de786c38326f..3d4e5caa9b27 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -110,7 +110,7 @@ macro_rules! arena_types { rustc_hir::def_id::DefId, rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>> >, - [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, + [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>, [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap, [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem, diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 3b6eecb7fa04..b35cc83cb8e8 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -64,7 +64,7 @@ impl<'tcx> ExportedSymbol<'tcx> { tcx.symbol_name(ty::Instance::resolve_async_drop_in_place(tcx, ty)) } ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance { - def: ty::InstanceDef::ThreadLocalShim(def_id), + def: ty::InstanceKind::ThreadLocalShim(def_id), args: ty::GenericArgs::empty(), }), ExportedSymbol::NoDefId(symbol_name) => symbol_name, diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs index 96bef40dac51..2eadc4d553cc 100644 --- a/compiler/rustc_middle/src/mir/graphviz.rs +++ b/compiler/rustc_middle/src/mir/graphviz.rs @@ -19,7 +19,7 @@ where if tcx.is_const_fn_raw(*def_id) { vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)] } else { - vec![tcx.instance_mir(ty::InstanceDef::Item(*def_id))] + vec![tcx.instance_mir(ty::InstanceKind::Item(*def_id))] } }) .collect::>(); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index eabbcc2033f1..23680f143970 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -438,9 +438,6 @@ pub enum ValidationErrorKind<'tcx> { ptr_kind: PointerKind, ty: Ty<'tcx>, }, - PtrToStatic { - ptr_kind: PointerKind, - }, ConstRefToMutable, ConstRefToExtern, MutableRefToImmutable, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 02e5174a715d..01cefc75194f 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, Instance, InstanceKind, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; @@ -233,7 +233,7 @@ impl RuntimePhase { #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub struct MirSource<'tcx> { - pub instance: InstanceDef<'tcx>, + pub instance: InstanceKind<'tcx>, /// If `Some`, this is a promoted rvalue within the parent function. pub promoted: Option, @@ -241,10 +241,10 @@ pub struct MirSource<'tcx> { impl<'tcx> MirSource<'tcx> { pub fn item(def_id: DefId) -> Self { - MirSource { instance: InstanceDef::Item(def_id), promoted: None } + MirSource { instance: InstanceKind::Item(def_id), promoted: None } } - pub fn from_instance(instance: InstanceDef<'tcx>) -> Self { + pub fn from_instance(instance: InstanceKind<'tcx>) -> Self { MirSource { instance, promoted: None } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 3d79ec0092f8..146cd6dfbeb7 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,5 +1,5 @@ use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; -use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt}; +use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; use rustc_data_structures::base_n::BaseNString; use rustc_data_structures::base_n::ToBaseN; @@ -56,7 +56,7 @@ impl<'tcx> MonoItem<'tcx> { /// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims). pub fn is_user_defined(&self) -> bool { match *self { - MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)), + MonoItem::Fn(instance) => matches!(instance.def, InstanceKind::Item(..)), MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true, } } @@ -69,9 +69,9 @@ impl<'tcx> MonoItem<'tcx> { match instance.def { // "Normal" functions size estimate: the number of // statements, plus one for the terminator. - InstanceDef::Item(..) - | InstanceDef::DropGlue(..) - | InstanceDef::AsyncDropGlueCtorShim(..) => { + InstanceKind::Item(..) + | InstanceKind::DropGlue(..) + | InstanceKind::AsyncDropGlueCtorShim(..) => { let mir = tcx.instance_mir(instance.def); mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() } @@ -407,20 +407,20 @@ impl<'tcx> CodegenUnit<'tcx> { // instances into account. The others don't matter for // the codegen tests and can even make item order // unstable. - InstanceDef::Item(def) => def.as_local().map(Idx::index), - InstanceDef::VTableShim(..) - | InstanceDef::ReifyShim(..) - | InstanceDef::Intrinsic(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::Virtual(..) - | InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineKindShim { .. } - | InstanceDef::DropGlue(..) - | InstanceDef::CloneShim(..) - | InstanceDef::ThreadLocalShim(..) - | InstanceDef::FnPtrAddrShim(..) - | InstanceDef::AsyncDropGlueCtorShim(..) => None, + InstanceKind::Item(def) => def.as_local().map(Idx::index), + InstanceKind::VTableShim(..) + | InstanceKind::ReifyShim(..) + | InstanceKind::Intrinsic(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::CoroutineKindShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::CloneShim(..) + | InstanceKind::ThreadLocalShim(..) + | InstanceKind::FnPtrAddrShim(..) + | InstanceKind::AsyncDropGlueCtorShim(..) => None, } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f1c3cb698969..4657f4dcf813 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -177,7 +177,7 @@ fn dump_path<'tcx>( // All drop shims have the same DefId, so we have to add the type // to get unique file names. let shim_disambiguator = match source.instance { - ty::InstanceDef::DropGlue(_, Some(ty)) => { + ty::InstanceKind::DropGlue(_, Some(ty)) => { // Unfortunately, pretty-printed typed are not very filename-friendly. // We dome some filtering. let mut s = ".".to_owned(); @@ -188,7 +188,7 @@ fn dump_path<'tcx>( })); s } - ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => { + ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => { // Unfortunately, pretty-printed typed are not very filename-friendly. // We dome some filtering. let mut s = ".".to_owned(); @@ -280,7 +280,7 @@ pub fn write_mir_pretty<'tcx>( // are shared between mir_for_ctfe and optimized_mir write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?; } else { - let instance_mir = tcx.instance_mir(ty::InstanceDef::Item(def_id)); + let instance_mir = tcx.instance_mir(ty::InstanceKind::Item(def_id)); render_body(w, instance_mir)?; } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 10609e56f2c4..7628a1ed2fe2 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -337,27 +337,27 @@ macro_rules! make_mir_visitor { let ty::Instance { def: callee_def, args: callee_args } = callee; match callee_def { - ty::InstanceDef::Item(_def_id) => {} + ty::InstanceKind::Item(_def_id) => {} - ty::InstanceDef::Intrinsic(_def_id) | - ty::InstanceDef::VTableShim(_def_id) | - ty::InstanceDef::ReifyShim(_def_id, _) | - ty::InstanceDef::Virtual(_def_id, _) | - ty::InstanceDef::ThreadLocalShim(_def_id) | - ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | - ty::InstanceDef::ConstructCoroutineInClosureShim { + ty::InstanceKind::Intrinsic(_def_id) | + ty::InstanceKind::VTableShim(_def_id) | + ty::InstanceKind::ReifyShim(_def_id, _) | + ty::InstanceKind::Virtual(_def_id, _) | + ty::InstanceKind::ThreadLocalShim(_def_id) | + ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ } | + ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, receiver_by_ref: _, } | - ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } | - ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, None) | - ty::InstanceDef::DropGlue(_def_id, None) => {} + ty::InstanceKind::CoroutineKindShim { coroutine_def_id: _def_id } | + ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) | + ty::InstanceKind::DropGlue(_def_id, None) => {} - ty::InstanceDef::FnPtrShim(_def_id, ty) | - ty::InstanceDef::DropGlue(_def_id, Some(ty)) | - ty::InstanceDef::CloneShim(_def_id, ty) | - ty::InstanceDef::FnPtrAddrShim(_def_id, ty) | - ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, Some(ty)) => { + ty::InstanceKind::FnPtrShim(_def_id, ty) | + ty::InstanceKind::DropGlue(_def_id, Some(ty)) | + ty::InstanceKind::CloneShim(_def_id, ty) | + ty::InstanceKind::FnPtrAddrShim(_def_id, ty) | + ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => { // FIXME(eddyb) use a better `TyContext` here. self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b29a86d58ed6..301c9911b44c 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -365,7 +365,7 @@ tcx_lifetime! { rustc_middle::ty::GenericPredicates, rustc_middle::ty::inhabitedness::InhabitedPredicate, rustc_middle::ty::Instance, - rustc_middle::ty::InstanceDef, + rustc_middle::ty::InstanceKind, rustc_middle::ty::layout::FnAbiError, rustc_middle::ty::layout::LayoutError, rustc_middle::ty::ParamEnv, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 5452e1dff3ef..add88491f846 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -62,7 +62,7 @@ impl Key for () { } } -impl<'tcx> Key for ty::InstanceDef<'tcx> { +impl<'tcx> Key for ty::InstanceKind<'tcx> { type Cache = DefaultCache; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -70,7 +70,7 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> { } } -impl<'tcx> AsLocalKey for ty::InstanceDef<'tcx> { +impl<'tcx> AsLocalKey for ty::InstanceKind<'tcx> { type LocalKey = Self; #[inline(always)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8ba930f493e2..0f08694c4eab 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -575,7 +575,7 @@ rustc_queries! { /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations /// have had a chance to potentially remove some of them. - query coverage_ids_info(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageIdsInfo { + query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> &'tcx mir::CoverageIdsInfo { desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } arena_cache } @@ -1033,7 +1033,7 @@ rustc_queries! { } /// Obtain all the calls into other local functions - query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { + query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { fatal_cycle desc { |tcx| "computing all local function calls in `{}`", @@ -1140,7 +1140,7 @@ rustc_queries! { } /// Generates a MIR body for the shim. - query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> { + query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { arena_cache desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } } @@ -1410,7 +1410,7 @@ rustc_queries! { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. /// /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` - /// instead, where the instance is an `InstanceDef::Virtual`. + /// instead, where the instance is an `InstanceKind::Virtual`. query fn_abi_of_fn_ptr( key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { @@ -1421,7 +1421,7 @@ rustc_queries! { /// direct calls to an `fn`. /// /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceDef::Virtual` instance (of `::fn`). + /// to an `InstanceKind::Virtual` instance (of `::fn`). query fn_abi_of_instance( key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { @@ -1918,7 +1918,7 @@ rustc_queries! { desc { "getting codegen unit `{sym}`" } } - query unused_generic_params(key: ty::InstanceDef<'tcx>) -> UnusedGenericParams { + query unused_generic_params(key: ty::InstanceKind<'tcx>) -> UnusedGenericParams { cache_on_disk_if { key.def_id().is_local() } desc { |tcx| "determining which generic parameters are unused by `{}`", diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 202d587f0ad2..b4e3fae1b43b 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -32,54 +32,7 @@ use std::hash::{Hash, Hasher}; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; // FIXME: Remove this import and import via `solve::` -pub use rustc_type_ir::solve::BuiltinImplSource; - -/// Depending on the stage of compilation, we want projection to be -/// more or less conservative. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)] -pub enum Reveal { - /// At type-checking time, we refuse to project any associated - /// type that is marked `default`. Non-`default` ("final") types - /// are always projected. This is necessary in general for - /// soundness of specialization. However, we *could* allow - /// projections in fully-monomorphic cases. We choose not to, - /// because we prefer for `default type` to force the type - /// definition to be treated abstractly by any consumers of the - /// impl. Concretely, that means that the following example will - /// fail to compile: - /// - /// ```compile_fail,E0308 - /// #![feature(specialization)] - /// trait Assoc { - /// type Output; - /// } - /// - /// impl Assoc for T { - /// default type Output = bool; - /// } - /// - /// fn main() { - /// let x: <() as Assoc>::Output = true; - /// } - /// ``` - /// - /// We also do not reveal the hidden type of opaque types during - /// type-checking. - UserFacing, - - /// At codegen time, all monomorphic projections will succeed. - /// Also, `impl Trait` is normalized to the concrete type, - /// which has to be already collected by type-checking. - /// - /// NOTE: as `impl Trait`'s concrete type should *never* - /// be observable directly by the user, `Reveal::All` - /// should not be used by checks which may expose - /// type equality or type contents to the user. - /// There are some exceptions, e.g., around auto traits and - /// transmute-checking, which expose some details, but - /// not the whole concrete type of the `impl Trait`. - All, -} +pub use rustc_type_ir::solve::{BuiltinImplSource, Reveal}; /// The reason why we incurred this obligation; used for error reporting. /// diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0d9ce402c64e..9e979620a440 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,10 +1,9 @@ use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; -use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; +use rustc_macros::HashStable; use rustc_type_ir as ir; pub use rustc_type_ir::solve::*; -use crate::infer::canonical::QueryRegionConstraints; use crate::ty::{ self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; @@ -38,37 +37,18 @@ impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> { } #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)] -pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); +pub struct ExternalConstraints<'tcx>( + pub(crate) Interned<'tcx, ExternalConstraintsData>>, +); impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { - type Target = ExternalConstraintsData<'tcx>; + type Target = ExternalConstraintsData>; fn deref(&self) -> &Self::Target { &self.0 } } -/// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)] -pub struct ExternalConstraintsData<'tcx> { - // FIXME: implement this. - pub region_constraints: QueryRegionConstraints<'tcx>, - pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, - pub normalization_nested_goals: NestedNormalizationGoals<'tcx>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)] -pub struct NestedNormalizationGoals<'tcx>(pub Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>); -impl<'tcx> NestedNormalizationGoals<'tcx> { - pub fn empty() -> Self { - NestedNormalizationGoals(vec![]) - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - // FIXME: Having to clone `region_constraints` for folding feels bad and // probably isn't great wrt performance. // diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3651c990c979..e2f15dac0198 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -88,6 +88,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; + type LocalDefId = LocalDefId; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; @@ -382,7 +383,7 @@ pub struct CtxtInterners<'tcx> { bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, adt_def: InternedSet<'tcx, AdtDefData>, - external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>, + external_constraints: InternedSet<'tcx, ExternalConstraintsData>>, predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>, fields: InternedSet<'tcx, List>, local_def_ids: InternedSet<'tcx, List>, @@ -2093,7 +2094,7 @@ direct_interners! { const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, - external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>): + external_constraints: pub mk_external_constraints(ExternalConstraintsData>): ExternalConstraints -> ExternalConstraints<'tcx>, predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>): PredefinedOpaques -> PredefinedOpaques<'tcx>, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index bdf90cbb25bb..5718264c9446 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -19,10 +19,10 @@ use tracing::{debug, instrument}; use std::assert_matches::assert_matches; use std::fmt; -/// A monomorphized `InstanceDef`. +/// An `InstanceKind` along with the args that are needed to substitute the instance. /// /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type -/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval +/// simply couples a potentially generic `InstanceKind` with some args, and codegen and const eval /// will do all required instantiations as they run. /// /// Note: the `Lift` impl is currently not used by rustc, but is used by @@ -30,7 +30,7 @@ use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] pub struct Instance<'tcx> { - pub def: InstanceDef<'tcx>, + pub def: InstanceKind<'tcx>, pub args: GenericArgsRef<'tcx>, } @@ -58,7 +58,7 @@ pub enum ReifyReason { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum InstanceDef<'tcx> { +pub enum InstanceKind<'tcx> { /// A user-defined callable item. /// /// This includes: @@ -69,7 +69,7 @@ pub enum InstanceDef<'tcx> { /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI). /// - /// Alongside `Virtual`, this is the only `InstanceDef` that does not have its own callable MIR. + /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR. /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the /// caller. Intrinsic(DefId), @@ -85,7 +85,7 @@ pub enum InstanceDef<'tcx> { /// /// One example is `::fn`, where the shim contains /// a virtual call, which codegen supports only via a direct call to the - /// `::fn` instance (an `InstanceDef::Virtual`). + /// `::fn` instance (an `InstanceKind::Virtual`). /// /// Another example is functions annotated with `#[track_caller]`, which /// must have their implicit caller location argument populated for a call. @@ -107,7 +107,7 @@ pub enum InstanceDef<'tcx> { /// Dynamic dispatch to `::fn`. /// - /// This `InstanceDef` does not have callable MIR. Calls to `Virtual` instances must be + /// This `InstanceKind` does not have callable MIR. Calls to `Virtual` instances must be /// codegen'd as virtual calls through the vtable. /// /// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more @@ -216,10 +216,10 @@ impl<'tcx> Instance<'tcx> { } match self.def { - InstanceDef::Item(def) => tcx + InstanceKind::Item(def) => tcx .upstream_monomorphizations_for(def) .and_then(|monos| monos.get(&self.args).cloned()), - InstanceDef::DropGlue(_, Some(_)) | InstanceDef::AsyncDropGlueCtorShim(_, _) => { + InstanceKind::DropGlue(_, Some(_)) | InstanceKind::AsyncDropGlueCtorShim(_, _) => { tcx.upstream_drop_glue_for(self.args) } _ => None, @@ -227,48 +227,48 @@ impl<'tcx> Instance<'tcx> { } } -impl<'tcx> InstanceDef<'tcx> { +impl<'tcx> InstanceKind<'tcx> { #[inline] pub fn def_id(self) -> DefId { match self { - InstanceDef::Item(def_id) - | InstanceDef::VTableShim(def_id) - | InstanceDef::ReifyShim(def_id, _) - | InstanceDef::FnPtrShim(def_id, _) - | InstanceDef::Virtual(def_id, _) - | InstanceDef::Intrinsic(def_id) - | InstanceDef::ThreadLocalShim(def_id) - | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } - | ty::InstanceDef::ConstructCoroutineInClosureShim { + InstanceKind::Item(def_id) + | InstanceKind::VTableShim(def_id) + | InstanceKind::ReifyShim(def_id, _) + | InstanceKind::FnPtrShim(def_id, _) + | InstanceKind::Virtual(def_id, _) + | InstanceKind::Intrinsic(def_id) + | InstanceKind::ThreadLocalShim(def_id) + | InstanceKind::ClosureOnceShim { call_once: def_id, track_caller: _ } + | ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id: def_id, receiver_by_ref: _, } - | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id } - | InstanceDef::DropGlue(def_id, _) - | InstanceDef::CloneShim(def_id, _) - | InstanceDef::FnPtrAddrShim(def_id, _) - | InstanceDef::AsyncDropGlueCtorShim(def_id, _) => def_id, + | ty::InstanceKind::CoroutineKindShim { coroutine_def_id: def_id } + | InstanceKind::DropGlue(def_id, _) + | InstanceKind::CloneShim(def_id, _) + | InstanceKind::FnPtrAddrShim(def_id, _) + | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id, } } /// Returns the `DefId` of instances which might not require codegen locally. pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option { match self { - ty::InstanceDef::Item(def) => Some(def), - ty::InstanceDef::DropGlue(def_id, Some(_)) - | InstanceDef::AsyncDropGlueCtorShim(def_id, _) - | InstanceDef::ThreadLocalShim(def_id) => Some(def_id), - InstanceDef::VTableShim(..) - | InstanceDef::ReifyShim(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::Virtual(..) - | InstanceDef::Intrinsic(..) - | InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | InstanceDef::DropGlue(..) - | InstanceDef::CloneShim(..) - | InstanceDef::FnPtrAddrShim(..) => None, + ty::InstanceKind::Item(def) => Some(def), + ty::InstanceKind::DropGlue(def_id, Some(_)) + | InstanceKind::AsyncDropGlueCtorShim(def_id, _) + | InstanceKind::ThreadLocalShim(def_id) => Some(def_id), + InstanceKind::VTableShim(..) + | InstanceKind::ReifyShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::Intrinsic(..) + | InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::CloneShim(..) + | InstanceKind::FnPtrAddrShim(..) => None, } } @@ -289,10 +289,10 @@ impl<'tcx> InstanceDef<'tcx> { pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool { use rustc_hir::definitions::DefPathData; let def_id = match *self { - ty::InstanceDef::Item(def) => def, - ty::InstanceDef::DropGlue(_, Some(_)) => return false, - ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => return false, - ty::InstanceDef::ThreadLocalShim(_) => return false, + ty::InstanceKind::Item(def) => def, + ty::InstanceKind::DropGlue(_, Some(_)) => return false, + ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => return false, + ty::InstanceKind::ThreadLocalShim(_) => return false, _ => return true, }; matches!( @@ -312,7 +312,7 @@ impl<'tcx> InstanceDef<'tcx> { if self.requires_inline(tcx) { return true; } - if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self { + if let ty::InstanceKind::DropGlue(.., Some(ty)) = *self { // Drop glue generally wants to be instantiated at every codegen // unit, but without an #[inline] hint. We should make this // available to normal end-users. @@ -332,7 +332,7 @@ impl<'tcx> InstanceDef<'tcx> { .map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did)) }); } - if let ty::InstanceDef::ThreadLocalShim(..) = *self { + if let ty::InstanceKind::ThreadLocalShim(..) = *self { return false; } tcx.cross_crate_inlinable(self.def_id()) @@ -340,10 +340,10 @@ impl<'tcx> InstanceDef<'tcx> { pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { match *self { - InstanceDef::Item(def_id) | InstanceDef::Virtual(def_id, _) => { + InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => { tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } - InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller, + InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller, _ => false, } } @@ -356,22 +356,22 @@ impl<'tcx> InstanceDef<'tcx> { /// body should perform necessary instantiations. pub fn has_polymorphic_mir_body(&self) -> bool { match *self { - InstanceDef::CloneShim(..) - | InstanceDef::ThreadLocalShim(..) - | InstanceDef::FnPtrAddrShim(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::DropGlue(_, Some(_)) - | InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => false, - InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineKindShim { .. } - | InstanceDef::DropGlue(..) - | InstanceDef::AsyncDropGlueCtorShim(..) - | InstanceDef::Item(_) - | InstanceDef::Intrinsic(..) - | InstanceDef::ReifyShim(..) - | InstanceDef::Virtual(..) - | InstanceDef::VTableShim(..) => true, + InstanceKind::CloneShim(..) + | InstanceKind::ThreadLocalShim(..) + | InstanceKind::FnPtrAddrShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::DropGlue(_, Some(_)) + | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false, + InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::CoroutineKindShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::AsyncDropGlueCtorShim(..) + | InstanceKind::Item(_) + | InstanceKind::Intrinsic(..) + | InstanceKind::ReifyShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::VTableShim(..) => true, } } } @@ -395,24 +395,24 @@ fn fmt_instance( })?; match instance.def { - InstanceDef::Item(_) => Ok(()), - InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"), - InstanceDef::ReifyShim(_, None) => write!(f, " - shim(reify)"), - InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"), - InstanceDef::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"), - InstanceDef::ThreadLocalShim(_) => write!(f, " - shim(tls)"), - InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"), - InstanceDef::Virtual(_, num) => write!(f, " - virtual#{num}"), - InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), - InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), - InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), - InstanceDef::CoroutineKindShim { .. } => write!(f, " - shim"), - InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), - InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), - InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), - InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"), - InstanceDef::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"), - InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), + InstanceKind::Item(_) => Ok(()), + InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"), + InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"), + InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"), + InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"), + InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"), + InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"), + InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"), + InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), + InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"), + InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), + InstanceKind::CoroutineKindShim { .. } => write!(f, " - shim"), + InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"), + InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), + InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"), + InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"), + InstanceKind::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"), + InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), } } @@ -434,9 +434,9 @@ impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { assert!( !args.has_escaping_bound_vars(), - "args of instance {def_id:?} not normalized for codegen: {args:?}" + "args of instance {def_id:?} has escaping bound vars: {args:?}" ); - Instance { def: InstanceDef::Item(def_id), args } + Instance { def: InstanceKind::Item(def_id), args } } pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { @@ -526,13 +526,13 @@ impl<'tcx> Instance<'tcx> { let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr); Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { - InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => { + InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); - resolved.def = InstanceDef::ReifyShim(def, reason); + resolved.def = InstanceKind::ReifyShim(def, reason); } - InstanceDef::Virtual(def_id, _) => { + InstanceKind::Virtual(def_id, _) => { debug!(" => fn pointer created for virtual call"); - resolved.def = InstanceDef::ReifyShim(def_id, reason); + resolved.def = InstanceKind::ReifyShim(def_id, reason); } // Reify `Trait::method` implementations if KCFI is enabled // FIXME(maurer) only reify it if it is a vtable-safe function @@ -544,7 +544,7 @@ impl<'tcx> Instance<'tcx> { { // If this function could also go in a vtable, we need to `ReifyShim` it with // KCFI because it can only attach one type per function. - resolved.def = InstanceDef::ReifyShim(resolved.def_id(), reason) + resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason) } // Reify `::call`-like method implementations if KCFI is enabled _ if tcx.sess.is_sanitizer_kcfi_enabled() @@ -553,7 +553,7 @@ impl<'tcx> Instance<'tcx> { // Reroute through a reify via the *unresolved* instance. The resolved one can't // be directly reified because it's closure-like. The reify can handle the // unresolved instance. - resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args } + resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args } } _ => {} } @@ -575,12 +575,12 @@ impl<'tcx> Instance<'tcx> { && tcx.generics_of(def_id).has_self; if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); - Some(Instance { def: InstanceDef::VTableShim(def_id), args }) + Some(Instance { def: InstanceKind::VTableShim(def_id), args }) } else { let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { - InstanceDef::Item(def) => { + InstanceKind::Item(def) => { // We need to generate a shim when we cannot guarantee that // the caller of a trait object method will be aware of // `#[track_caller]` - this ensures that the caller @@ -614,18 +614,18 @@ impl<'tcx> Instance<'tcx> { // Create a shim for the `FnOnce/FnMut/Fn` method we are calling // - unlike functions, invoking a closure always goes through a // trait. - resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args }; + resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }; } else { debug!( " => vtable fn pointer created for function with #[track_caller]: {:?}", def ); - resolved.def = InstanceDef::ReifyShim(def, reason); + resolved.def = InstanceKind::ReifyShim(def, reason); } } } - InstanceDef::Virtual(def_id, _) => { + InstanceKind::Virtual(def_id, _) => { debug!(" => vtable fn pointer created for virtual call"); - resolved.def = InstanceDef::ReifyShim(def_id, reason) + resolved.def = InstanceKind::ReifyShim(def_id, reason) } _ => {} } @@ -676,7 +676,7 @@ impl<'tcx> Instance<'tcx> { .def_id; let track_caller = tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); - let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller }; + let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller }; let self_ty = Ty::new_closure(tcx, closure_did, args); @@ -733,10 +733,10 @@ impl<'tcx> Instance<'tcx> { // If the closure's kind ty disagrees with the identity closure's kind ty, // then this must be a coroutine generated by one of the `ConstructCoroutineInClosureShim`s. if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() { - Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) + Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args }) } else { Some(Instance { - def: ty::InstanceDef::CoroutineKindShim { coroutine_def_id }, + def: ty::InstanceKind::CoroutineKindShim { coroutine_def_id }, args, }) } @@ -749,7 +749,7 @@ impl<'tcx> Instance<'tcx> { } } - /// Depending on the kind of `InstanceDef`, the MIR body associated with an + /// Depending on the kind of `InstanceKind`, the MIR body associated with an /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other /// cases the MIR body is expressed in terms of the types found in the generic parameter array. /// In the former case, we want to instantiate those generic types and replace them with the @@ -832,7 +832,7 @@ impl<'tcx> Instance<'tcx> { fn polymorphize<'tcx>( tcx: TyCtxt<'tcx>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { debug!("polymorphize({:?}, {:?})", instance, args); @@ -873,7 +873,7 @@ fn polymorphize<'tcx>( match *ty.kind() { ty::Closure(def_id, args) => { let polymorphized_args = - polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args); + polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args); if args == polymorphized_args { ty } else { @@ -882,7 +882,7 @@ fn polymorphize<'tcx>( } ty::Coroutine(def_id, args) => { let polymorphized_args = - polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args); + polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args); if args == polymorphized_args { ty } else { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 02c0d41f6190..cf7610bb4f61 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1302,7 +1302,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. /// /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` - /// instead, where the instance is an `InstanceDef::Virtual`. + /// instead, where the instance is an `InstanceKind::Virtual`. #[inline] fn fn_abi_of_fn_ptr( &self, @@ -1322,7 +1322,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// direct calls to an `fn`. /// /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceDef::Virtual` instance (of `::fn`). + /// to an `InstanceKind::Virtual` instance (of `::fn`). #[inline] #[tracing::instrument(level = "debug", skip(self))] fn fn_abi_of_instance( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5a94a53e175e..d07541bad93d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -92,8 +92,9 @@ pub use self::context::{ tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, }; -pub use self::instance::{Instance, InstanceDef, ReifyReason, ShortInstance, UnusedGenericParams}; +pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams}; pub use self::list::{List, ListWithCachedTypeInfo}; +pub use self::opaque_types::OpaqueTypeKey; pub use self::parameterized::ParameterizedOverTcx; pub use self::pattern::{Pattern, PatternKind}; pub use self::predicate::{ @@ -758,45 +759,6 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct OpaqueTypeKey<'tcx> { - pub def_id: LocalDefId, - pub args: GenericArgsRef<'tcx>, -} - -impl<'tcx> OpaqueTypeKey<'tcx> { - pub fn iter_captured_args( - self, - tcx: TyCtxt<'tcx>, - ) -> impl Iterator)> { - std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map( - |(i, (arg, v))| match (arg.unpack(), v) { - (_, ty::Invariant) => Some((i, arg)), - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None, - _ => bug!("unexpected opaque type arg variance"), - }, - ) - } - - pub fn fold_captured_lifetime_args( - self, - tcx: TyCtxt<'tcx>, - mut f: impl FnMut(Region<'tcx>) -> Region<'tcx>, - ) -> Self { - let Self { def_id, args } = self; - let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| { - match (arg.unpack(), v) { - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, - (ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(), - _ => arg, - } - }); - let args = tcx.mk_args_from_iter(args); - Self { def_id, args } - } -} - #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So @@ -1731,11 +1693,11 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Returns the possibly-auto-generated MIR of a [`ty::InstanceDef`]. + /// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`]. #[instrument(skip(self), level = "debug")] - pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { + pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> { match instance { - ty::InstanceDef::Item(def) => { + ty::InstanceKind::Item(def) => { debug!("calling def_kind on def: {:?}", def); let def_kind = self.def_kind(def); debug!("returned from def_kind: {:?}", def_kind); @@ -1751,19 +1713,19 @@ impl<'tcx> TyCtxt<'tcx> { _ => self.optimized_mir(def), } } - ty::InstanceDef::VTableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::Intrinsic(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::Virtual(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::CloneShim(..) - | ty::InstanceDef::ThreadLocalShim(..) - | ty::InstanceDef::FnPtrAddrShim(..) - | ty::InstanceDef::AsyncDropGlueCtorShim(..) => self.mir_shims(instance), + ty::InstanceKind::VTableShim(..) + | ty::InstanceKind::ReifyShim(..) + | ty::InstanceKind::Intrinsic(..) + | ty::InstanceKind::FnPtrShim(..) + | ty::InstanceKind::Virtual(..) + | ty::InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | ty::InstanceKind::DropGlue(..) + | ty::InstanceKind::CloneShim(..) + | ty::InstanceKind::ThreadLocalShim(..) + | ty::InstanceKind::FnPtrAddrShim(..) + | ty::InstanceKind::AsyncDropGlueCtorShim(..) => self.mir_shims(instance), } } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 52902aadd7c7..08b2f9e89203 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -7,6 +7,8 @@ use rustc_span::def_id::DefId; use rustc_span::Span; use tracing::{debug, instrument, trace}; +pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey>; + /// Converts generic params of a TypeFoldable from one /// item's generics to another. Usually from a function's generics /// list to the opaque type's own generics. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 84512e81637e..bf79b4e133a9 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -68,7 +68,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::CoroutineArgs; -use rustc_middle::ty::InstanceDef; +use rustc_middle::ty::InstanceKind; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ @@ -1276,7 +1276,7 @@ fn create_coroutine_drop_shim<'tcx>( // Update the body's def to become the drop glue. let coroutine_instance = body.source.instance; let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None); - let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty)); + let drop_instance = InstanceKind::DropGlue(drop_in_place, Some(coroutine_ty)); // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible // filename. diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 10c0567eb4b7..69d21a63f557 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -75,7 +75,7 @@ use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir, MirPass}; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_target::abi::{FieldIdx, VariantIdx}; pub struct ByMoveBody; @@ -102,7 +102,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { // We don't need to generate a by-move coroutine if the coroutine body was // produced by the `CoroutineKindShim`, since it's already by-move. - if matches!(body.source.instance, ty::InstanceDef::CoroutineKindShim { .. }) { + if matches!(body.source.instance, ty::InstanceKind::CoroutineKindShim { .. }) { return; } @@ -193,7 +193,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); // FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body. - by_move_body.source = mir::MirSource::from_instance(InstanceDef::CoroutineKindShim { + by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim { coroutine_def_id: coroutine_def_id.to_def_id(), }); body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index b5968517d772..a8b0f4a8d6df 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -168,11 +168,6 @@ impl CoverageCounters { self.counter_increment_sites.len() } - #[cfg(test)] - pub(super) fn num_expressions(&self) -> usize { - self.expressions.len() - } - fn set_bcb_counter(&mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter) -> BcbCounter { if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) { bug!( diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index fd74a2a97e2c..360dccb240dc 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -14,16 +14,16 @@ use std::ops::{Index, IndexMut}; /// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s /// nodes are `BasicCoverageBlock`s, which encompass one or more MIR `BasicBlock`s. #[derive(Debug)] -pub(super) struct CoverageGraph { +pub(crate) struct CoverageGraph { bcbs: IndexVec, bb_to_bcb: IndexVec>, - pub successors: IndexVec>, - pub predecessors: IndexVec>, + pub(crate) successors: IndexVec>, + pub(crate) predecessors: IndexVec>, dominators: Option>, } impl CoverageGraph { - pub fn from_mir(mir_body: &mir::Body<'_>) -> Self { + pub(crate) fn from_mir(mir_body: &mir::Body<'_>) -> Self { let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body); // Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock @@ -135,24 +135,28 @@ impl CoverageGraph { } #[inline(always)] - pub fn iter_enumerated( + pub(crate) fn iter_enumerated( &self, ) -> impl Iterator { self.bcbs.iter_enumerated() } #[inline(always)] - pub fn bcb_from_bb(&self, bb: BasicBlock) -> Option { + pub(crate) fn bcb_from_bb(&self, bb: BasicBlock) -> Option { if bb.index() < self.bb_to_bcb.len() { self.bb_to_bcb[bb] } else { None } } #[inline(always)] - pub fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool { + pub(crate) fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool { self.dominators.as_ref().unwrap().dominates(dom, node) } #[inline(always)] - pub fn cmp_in_dominator_order(&self, a: BasicCoverageBlock, b: BasicCoverageBlock) -> Ordering { + pub(crate) fn cmp_in_dominator_order( + &self, + a: BasicCoverageBlock, + b: BasicCoverageBlock, + ) -> Ordering { self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b) } @@ -166,7 +170,7 @@ impl CoverageGraph { /// /// FIXME: That assumption might not be true for [`TerminatorKind::Yield`]? #[inline(always)] - pub(super) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool { + pub(crate) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool { // Even though bcb0 conceptually has an extra virtual in-edge due to // being the entry point, we've already asserted that it has no _other_ // in-edges, so there's no possibility of it having _multiple_ in-edges. @@ -212,7 +216,7 @@ impl graph::StartNode for CoverageGraph { impl graph::Successors for CoverageGraph { #[inline] fn successors(&self, node: Self::Node) -> impl Iterator { - self.successors[node].iter().cloned() + self.successors[node].iter().copied() } } @@ -227,7 +231,7 @@ rustc_index::newtype_index! { /// A node in the control-flow graph of CoverageGraph. #[orderable] #[debug_format = "bcb{}"] - pub(super) struct BasicCoverageBlock { + pub(crate) struct BasicCoverageBlock { const START_BCB = 0; } } @@ -259,23 +263,23 @@ rustc_index::newtype_index! { /// queries (`dominates()`, `predecessors`, `successors`, etc.) have branch (control flow) /// significance. #[derive(Debug, Clone)] -pub(super) struct BasicCoverageBlockData { - pub basic_blocks: Vec, +pub(crate) struct BasicCoverageBlockData { + pub(crate) basic_blocks: Vec, } impl BasicCoverageBlockData { - pub fn from(basic_blocks: Vec) -> Self { + fn from(basic_blocks: Vec) -> Self { assert!(basic_blocks.len() > 0); Self { basic_blocks } } #[inline(always)] - pub fn leader_bb(&self) -> BasicBlock { + pub(crate) fn leader_bb(&self) -> BasicBlock { self.basic_blocks[0] } #[inline(always)] - pub fn last_bb(&self) -> BasicBlock { + pub(crate) fn last_bb(&self) -> BasicBlock { *self.basic_blocks.last().unwrap() } } @@ -364,7 +368,7 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera /// CoverageGraph outside all loops. This supports traversing the BCB CFG in a way that /// ensures a loop is completely traversed before processing Blocks after the end of the loop. #[derive(Debug)] -pub(super) struct TraversalContext { +struct TraversalContext { /// BCB with one or more incoming loop backedges, indicating which loop /// this context is for. /// @@ -375,7 +379,7 @@ pub(super) struct TraversalContext { worklist: VecDeque, } -pub(super) struct TraverseCoverageGraphWithLoops<'a> { +pub(crate) struct TraverseCoverageGraphWithLoops<'a> { basic_coverage_blocks: &'a CoverageGraph, backedges: IndexVec>, @@ -384,7 +388,7 @@ pub(super) struct TraverseCoverageGraphWithLoops<'a> { } impl<'a> TraverseCoverageGraphWithLoops<'a> { - pub(super) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self { + pub(crate) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self { let backedges = find_loop_backedges(basic_coverage_blocks); let worklist = VecDeque::from([basic_coverage_blocks.start_node()]); @@ -400,7 +404,7 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { /// For each loop on the loop context stack (top-down), yields a list of BCBs /// within that loop that have an outgoing edge back to the loop header. - pub(super) fn reloop_bcbs_per_loop(&self) -> impl Iterator { + pub(crate) fn reloop_bcbs_per_loop(&self) -> impl Iterator { self.context_stack .iter() .rev() @@ -408,39 +412,38 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { .map(|header_bcb| self.backedges[header_bcb].as_slice()) } - pub(super) fn next(&mut self) -> Option { + pub(crate) fn next(&mut self) -> Option { debug!( "TraverseCoverageGraphWithLoops::next - context_stack: {:?}", self.context_stack.iter().rev().collect::>() ); while let Some(context) = self.context_stack.last_mut() { - if let Some(bcb) = context.worklist.pop_front() { - if !self.visited.insert(bcb) { - debug!("Already visited: {bcb:?}"); - continue; - } - debug!("Visiting {bcb:?}"); - - if self.backedges[bcb].len() > 0 { - debug!("{bcb:?} is a loop header! Start a new TraversalContext..."); - self.context_stack.push(TraversalContext { - loop_header: Some(bcb), - worklist: VecDeque::new(), - }); - } - self.add_successors_to_worklists(bcb); - return Some(bcb); - } else { - // Strip contexts with empty worklists from the top of the stack + let Some(bcb) = context.worklist.pop_front() else { + // This stack level is exhausted; pop it and try the next one. self.context_stack.pop(); + continue; + }; + + if !self.visited.insert(bcb) { + debug!("Already visited: {bcb:?}"); + continue; } + debug!("Visiting {bcb:?}"); + + if self.backedges[bcb].len() > 0 { + debug!("{bcb:?} is a loop header! Start a new TraversalContext..."); + self.context_stack + .push(TraversalContext { loop_header: Some(bcb), worklist: VecDeque::new() }); + } + self.add_successors_to_worklists(bcb); + return Some(bcb); } None } - pub fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) { + fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) { let successors = &self.basic_coverage_blocks.successors[bcb]; debug!("{:?} has {} successors:", bcb, successors.len()); @@ -494,11 +497,11 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { } } - pub fn is_complete(&self) -> bool { + pub(crate) fn is_complete(&self) -> bool { self.visited.count() == self.visited.domain_size() } - pub fn unvisited(&self) -> Vec { + pub(crate) fn unvisited(&self) -> Vec { let mut unvisited_set: BitSet = BitSet::new_filled(self.visited.domain_size()); unvisited_set.subtract(&self.visited); @@ -506,7 +509,7 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { } } -pub(super) fn find_loop_backedges( +fn find_loop_backedges( basic_coverage_blocks: &CoverageGraph, ) -> IndexVec> { let num_bcbs = basic_coverage_blocks.num_nodes(); diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 65715253647a..25744009be8b 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -49,7 +49,7 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// Query implementation for `coverage_ids_info`. fn coverage_ids_info<'tcx>( tcx: TyCtxt<'tcx>, - instance_def: ty::InstanceDef<'tcx>, + instance_def: ty::InstanceKind<'tcx>, ) -> CoverageIdsInfo { let mir_body = tcx.instance_mir(instance_def); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index bb6a666ff73b..84a70d1f02d7 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,9 +1,15 @@ +use std::collections::VecDeque; + +use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_span::Span; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; use crate::coverage::mappings; -use crate::coverage::spans::from_mir::SpanFromMir; +use crate::coverage::spans::from_mir::{ + extract_covspans_and_holes_from_mir, ExtractedCovspans, Hole, SpanFromMir, +}; use crate::coverage::ExtractedHirInfo; mod from_mir; @@ -19,50 +25,181 @@ pub(super) fn extract_refined_covspans( basic_coverage_blocks: &CoverageGraph, code_mappings: &mut impl Extend, ) { - let sorted_span_buckets = - from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); - for bucket in sorted_span_buckets { - let refined_spans = refine_sorted_spans(bucket); - code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| { + let ExtractedCovspans { mut covspans, mut holes } = + extract_covspans_and_holes_from_mir(mir_body, hir_info, basic_coverage_blocks); + + // First, perform the passes that need macro information. + covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)); + remove_unwanted_macro_spans(&mut covspans); + split_visible_macro_spans(&mut covspans); + + // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`. + let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::>(); + + let compare_covspans = |a: &Covspan, b: &Covspan| { + compare_spans(a.span, b.span) + // After deduplication, we want to keep only the most-dominated BCB. + .then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse()) + }; + covspans.sort_by(compare_covspans); + + // Among covspans with the same span, keep only one, + // preferring the one with the most-dominated BCB. + // (Ideally we should try to preserve _all_ non-dominating BCBs, but that + // requires a lot more complexity in the span refiner, for little benefit.) + covspans.dedup_by(|b, a| a.span.source_equal(b.span)); + + // Sort the holes, and merge overlapping/adjacent holes. + holes.sort_by(|a, b| compare_spans(a.span, b.span)); + holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); + + // Split the covspans into separate buckets that don't overlap any holes. + let buckets = divide_spans_into_buckets(covspans, &holes); + + for mut covspans in buckets { + // Make sure each individual bucket is internally sorted. + covspans.sort_by(compare_covspans); + let _span = debug_span!("processing bucket", ?covspans).entered(); + + let mut covspans = remove_unwanted_overlapping_spans(covspans); + debug!(?covspans, "after removing overlaps"); + + // Do one last merge pass, to simplify the output. + covspans.dedup_by(|b, a| a.merge_if_eligible(b)); + debug!(?covspans, "after merge"); + + code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| { // Each span produced by the refiner represents an ordinary code region. mappings::CodeMapping { span, bcb } })); } } -#[derive(Debug)] -struct RefinedCovspan { - span: Span, - bcb: BasicCoverageBlock, +/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate +/// multiple condition/consequent blocks that have the span of the whole macro +/// invocation, which is unhelpful. Keeping only the first such span seems to +/// give better mappings, so remove the others. +/// +/// (The input spans should be sorted in BCB dominator order, so that the +/// retained "first" span is likely to dominate the others.) +fn remove_unwanted_macro_spans(covspans: &mut Vec) { + let mut seen_macro_spans = FxHashSet::default(); + covspans.retain(|covspan| { + // Ignore (retain) non-macro-expansion spans. + if covspan.visible_macro.is_none() { + return true; + } + + // Retain only the first macro-expanded covspan with this span. + seen_macro_spans.insert(covspan.span) + }); } -impl RefinedCovspan { - fn is_mergeable(&self, other: &Self) -> bool { - self.bcb == other.bcb +/// When a span corresponds to a macro invocation that is visible from the +/// function body, split it into two parts. The first part covers just the +/// macro name plus `!`, and the second part covers the rest of the macro +/// invocation. This seems to give better results for code that uses macros. +fn split_visible_macro_spans(covspans: &mut Vec) { + let mut extra_spans = vec![]; + + covspans.retain(|covspan| { + let Some(visible_macro) = covspan.visible_macro else { return true }; + + let split_len = visible_macro.as_str().len() as u32 + 1; + let (before, after) = covspan.span.split_at(split_len); + if !covspan.span.contains(before) || !covspan.span.contains(after) { + // Something is unexpectedly wrong with the split point. + // The debug assertion in `split_at` will have already caught this, + // but in release builds it's safer to do nothing and maybe get a + // bug report for unexpected coverage, rather than risk an ICE. + return true; + } + + extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb)); + extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb)); + false // Discard the original covspan that we just split. + }); + + // The newly-split spans are added at the end, so any previous sorting + // is not preserved. + covspans.extend(extra_spans); +} + +/// Uses the holes to divide the given covspans into buckets, such that: +/// - No span in any hole overlaps a bucket (truncating the spans if necessary). +/// - The spans in each bucket are strictly after all spans in previous buckets, +/// and strictly before all spans in subsequent buckets. +/// +/// The resulting buckets are sorted relative to each other, but might not be +/// internally sorted. +#[instrument(level = "debug")] +fn divide_spans_into_buckets(input_covspans: Vec, holes: &[Hole]) -> Vec> { + debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); + debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); + + // Now we're ready to start carving holes out of the initial coverage spans, + // and grouping them in buckets separated by the holes. + + let mut input_covspans = VecDeque::from(input_covspans); + let mut fragments = vec![]; + + // For each hole: + // - Identify the spans that are entirely or partly before the hole. + // - Put those spans in a corresponding bucket, truncated to the start of the hole. + // - If one of those spans also extends after the hole, put the rest of it + // in a "fragments" vector that is processed by the next hole. + let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); + for (hole, bucket) in holes.iter().zip(&mut buckets) { + let fragments_from_prev = std::mem::take(&mut fragments); + + // Only inspect spans that precede or overlap this hole, + // leaving the rest to be inspected by later holes. + // (This relies on the spans and holes both being sorted.) + let relevant_input_covspans = + drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()); + + for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) { + let (before, after) = covspan.split_around_hole_span(hole.span); + bucket.extend(before); + fragments.extend(after); + } } - fn merge_from(&mut self, other: &Self) { - debug_assert!(self.is_mergeable(other)); - self.span = self.span.to(other.span); - } + // After finding the spans before each hole, any remaining fragments/spans + // form their own final bucket, after the final hole. + // (If there were no holes, this will just be all of the initial spans.) + fragments.extend(input_covspans); + buckets.push(fragments); + + buckets +} + +/// Similar to `.drain(..)`, but stops just before it would remove an item not +/// satisfying the predicate. +fn drain_front_while<'a, T>( + queue: &'a mut VecDeque, + mut pred_fn: impl FnMut(&T) -> bool, +) -> impl Iterator + Captures<'a> { + std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) } /// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines" -/// those spans by removing spans that overlap in unwanted ways, and by merging -/// compatible adjacent spans. +/// those spans by removing spans that overlap in unwanted ways. #[instrument(level = "debug")] -fn refine_sorted_spans(sorted_spans: Vec) -> Vec { +fn remove_unwanted_overlapping_spans(sorted_spans: Vec) -> Vec { + debug_assert!(sorted_spans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); + // Holds spans that have been read from the input vector, but haven't yet // been committed to the output vector. let mut pending = vec![]; let mut refined = vec![]; for curr in sorted_spans { - pending.retain(|prev: &SpanFromMir| { + pending.retain(|prev: &Covspan| { if prev.span.hi() <= curr.span.lo() { // There's no overlap between the previous/current covspans, // so move the previous one into the refined list. - refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb }); + refined.push(prev.clone()); false } else { // Otherwise, retain the previous covspan only if it has the @@ -75,22 +212,57 @@ fn refine_sorted_spans(sorted_spans: Vec) -> Vec { } // Drain the rest of the pending list into the refined list. - for prev in pending { - refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb }); - } - - // Do one last merge pass, to simplify the output. - debug!(?refined, "before merge"); - refined.dedup_by(|b, a| { - if a.is_mergeable(b) { - debug!(?a, ?b, "merging list-adjacent refined spans"); - a.merge_from(b); - true - } else { - false - } - }); - debug!(?refined, "after merge"); - + refined.extend(pending); refined } + +#[derive(Clone, Debug)] +struct Covspan { + span: Span, + bcb: BasicCoverageBlock, +} + +impl Covspan { + /// Splits this covspan into 0-2 parts: + /// - The part that is strictly before the hole span, if any. + /// - The part that is strictly after the hole span, if any. + fn split_around_hole_span(&self, hole_span: Span) -> (Option, Option) { + let before = try { + let span = self.span.trim_end(hole_span)?; + Self { span, ..*self } + }; + let after = try { + let span = self.span.trim_start(hole_span)?; + Self { span, ..*self } + }; + + (before, after) + } + + /// If `self` and `other` can be merged (i.e. they have the same BCB), + /// mutates `self.span` to also include `other.span` and returns true. + /// + /// Note that compatible covspans can be merged even if their underlying + /// spans are not overlapping/adjacent; any space between them will also be + /// part of the merged covspan. + fn merge_if_eligible(&mut self, other: &Self) -> bool { + if self.bcb != other.bcb { + return false; + } + + self.span = self.span.to(other.span); + true + } +} + +/// Compares two spans in (lo ascending, hi descending) order. +fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering { + // First sort by span start. + Ord::cmp(&a.lo(), &b.lo()) + // If span starts are the same, sort by span end in reverse order. + // This ensures that if spans A and B are adjacent in the list, + // and they overlap but are not equal, then either: + // - Span A extends further left, or + // - Both have the same start and span A extends further right + .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse()) +} diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index b1f71035dded..09deb7534bfd 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,7 +1,3 @@ -use std::collections::VecDeque; - -use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::{ @@ -13,25 +9,25 @@ use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; use crate::coverage::graph::{ BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, }; +use crate::coverage::spans::Covspan; use crate::coverage::ExtractedHirInfo; +pub(crate) struct ExtractedCovspans { + pub(crate) covspans: Vec, + pub(crate) holes: Vec, +} + /// Traverses the MIR body to produce an initial collection of coverage-relevant /// spans, each associated with a node in the coverage graph (BCB) and possibly /// other metadata. -/// -/// The returned spans are divided into one or more buckets, such that: -/// - The spans in each bucket are strictly after all spans in previous buckets, -/// and strictly before all spans in subsequent buckets. -/// - The contents of each bucket are also sorted, in a specific order that is -/// expected by the subsequent span-refinement step. -pub(super) fn mir_to_initial_sorted_coverage_spans( +pub(crate) fn extract_covspans_and_holes_from_mir( mir_body: &mir::Body<'_>, hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, -) -> Vec> { +) -> ExtractedCovspans { let &ExtractedHirInfo { body_span, .. } = hir_info; - let mut initial_spans = vec![]; + let mut covspans = vec![]; let mut holes = vec![]; for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { @@ -40,150 +36,21 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( body_span, bcb, bcb_data, - &mut initial_spans, + &mut covspans, &mut holes, ); } // Only add the signature span if we found at least one span in the body. - if !initial_spans.is_empty() || !holes.is_empty() { + if !covspans.is_empty() || !holes.is_empty() { // If there is no usable signature span, add a fake one (before refinement) // to avoid an ugly gap between the body start and the first real span. // FIXME: Find a more principled way to solve this problem. let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()); - initial_spans.push(SpanFromMir::for_fn_sig(fn_sig_span)); + covspans.push(SpanFromMir::for_fn_sig(fn_sig_span)); } - initial_spans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)); - remove_unwanted_macro_spans(&mut initial_spans); - split_visible_macro_spans(&mut initial_spans); - - let compare_covspans = |a: &SpanFromMir, b: &SpanFromMir| { - compare_spans(a.span, b.span) - // After deduplication, we want to keep only the most-dominated BCB. - .then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse()) - }; - initial_spans.sort_by(compare_covspans); - - // Among covspans with the same span, keep only one, - // preferring the one with the most-dominated BCB. - // (Ideally we should try to preserve _all_ non-dominating BCBs, but that - // requires a lot more complexity in the span refiner, for little benefit.) - initial_spans.dedup_by(|b, a| a.span.source_equal(b.span)); - - // Sort the holes, and merge overlapping/adjacent holes. - holes.sort_by(|a, b| compare_spans(a.span, b.span)); - holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); - - // Now we're ready to start carving holes out of the initial coverage spans, - // and grouping them in buckets separated by the holes. - - let mut initial_spans = VecDeque::from(initial_spans); - let mut fragments: Vec = vec![]; - - // For each hole: - // - Identify the spans that are entirely or partly before the hole. - // - Put those spans in a corresponding bucket, truncated to the start of the hole. - // - If one of those spans also extends after the hole, put the rest of it - // in a "fragments" vector that is processed by the next hole. - let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); - for (hole, bucket) in holes.iter().zip(&mut buckets) { - let fragments_from_prev = std::mem::take(&mut fragments); - - // Only inspect spans that precede or overlap this hole, - // leaving the rest to be inspected by later holes. - // (This relies on the spans and holes both being sorted.) - let relevant_initial_spans = - drain_front_while(&mut initial_spans, |c| c.span.lo() < hole.span.hi()); - - for covspan in fragments_from_prev.into_iter().chain(relevant_initial_spans) { - let (before, after) = covspan.split_around_hole_span(hole.span); - bucket.extend(before); - fragments.extend(after); - } - } - - // After finding the spans before each hole, any remaining fragments/spans - // form their own final bucket, after the final hole. - // (If there were no holes, this will just be all of the initial spans.) - fragments.extend(initial_spans); - buckets.push(fragments); - - // Make sure each individual bucket is still internally sorted. - for bucket in &mut buckets { - bucket.sort_by(compare_covspans); - } - buckets -} - -fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering { - // First sort by span start. - Ord::cmp(&a.lo(), &b.lo()) - // If span starts are the same, sort by span end in reverse order. - // This ensures that if spans A and B are adjacent in the list, - // and they overlap but are not equal, then either: - // - Span A extends further left, or - // - Both have the same start and span A extends further right - .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse()) -} - -/// Similar to `.drain(..)`, but stops just before it would remove an item not -/// satisfying the predicate. -fn drain_front_while<'a, T>( - queue: &'a mut VecDeque, - mut pred_fn: impl FnMut(&T) -> bool, -) -> impl Iterator + Captures<'a> { - std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) -} - -/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate -/// multiple condition/consequent blocks that have the span of the whole macro -/// invocation, which is unhelpful. Keeping only the first such span seems to -/// give better mappings, so remove the others. -/// -/// (The input spans should be sorted in BCB dominator order, so that the -/// retained "first" span is likely to dominate the others.) -fn remove_unwanted_macro_spans(initial_spans: &mut Vec) { - let mut seen_macro_spans = FxHashSet::default(); - initial_spans.retain(|covspan| { - // Ignore (retain) non-macro-expansion spans. - if covspan.visible_macro.is_none() { - return true; - } - - // Retain only the first macro-expanded covspan with this span. - seen_macro_spans.insert(covspan.span) - }); -} - -/// When a span corresponds to a macro invocation that is visible from the -/// function body, split it into two parts. The first part covers just the -/// macro name plus `!`, and the second part covers the rest of the macro -/// invocation. This seems to give better results for code that uses macros. -fn split_visible_macro_spans(initial_spans: &mut Vec) { - let mut extra_spans = vec![]; - - initial_spans.retain(|covspan| { - let Some(visible_macro) = covspan.visible_macro else { return true }; - - let split_len = visible_macro.as_str().len() as u32 + 1; - let (before, after) = covspan.span.split_at(split_len); - if !covspan.span.contains(before) || !covspan.span.contains(after) { - // Something is unexpectedly wrong with the split point. - // The debug assertion in `split_at` will have already caught this, - // but in release builds it's safer to do nothing and maybe get a - // bug report for unexpected coverage, rather than risk an ICE. - return true; - } - - extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb)); - extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb)); - false // Discard the original covspan that we just split. - }); - - // The newly-split spans are added at the end, so any previous sorting - // is not preserved. - initial_spans.extend(extra_spans); + ExtractedCovspans { covspans, holes } } // Generate a set of coverage spans from the filtered set of `Statement`s and `Terminator`s of @@ -402,12 +269,12 @@ fn unexpand_into_body_span_with_prev( } #[derive(Debug)] -struct Hole { - span: Span, +pub(crate) struct Hole { + pub(crate) span: Span, } impl Hole { - fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool { + pub(crate) fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool { if !self.span.overlaps_or_adjacent(other.span) { return false; } @@ -418,7 +285,7 @@ impl Hole { } #[derive(Debug)] -pub(super) struct SpanFromMir { +pub(crate) struct SpanFromMir { /// A span that has been extracted from MIR and then "un-expanded" back to /// within the current function's `body_span`. After various intermediate /// processing steps, this span is emitted as part of the final coverage @@ -426,9 +293,9 @@ pub(super) struct SpanFromMir { /// /// With the exception of `fn_sig_span`, this should always be contained /// within `body_span`. - pub(super) span: Span, - visible_macro: Option, - pub(super) bcb: BasicCoverageBlock, + pub(crate) span: Span, + pub(crate) visible_macro: Option, + pub(crate) bcb: BasicCoverageBlock, } impl SpanFromMir { @@ -436,23 +303,12 @@ impl SpanFromMir { Self::new(fn_sig_span, None, START_BCB) } - fn new(span: Span, visible_macro: Option, bcb: BasicCoverageBlock) -> Self { + pub(crate) fn new(span: Span, visible_macro: Option, bcb: BasicCoverageBlock) -> Self { Self { span, visible_macro, bcb } } - /// Splits this span into 0-2 parts: - /// - The part that is strictly before the hole span, if any. - /// - The part that is strictly after the hole span, if any. - fn split_around_hole_span(&self, hole_span: Span) -> (Option, Option) { - let before = try { - let span = self.span.trim_end(hole_span)?; - Self { span, ..*self } - }; - let after = try { - let span = self.span.trim_start(hole_span)?; - Self { span, ..*self } - }; - - (before, after) + pub(crate) fn into_covspan(self) -> Covspan { + let Self { span, visible_macro: _, bcb } = self; + Covspan { span, bcb } } } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index ca64688e6b87..048547dc9f54 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -24,7 +24,6 @@ //! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`. -use super::counters; use super::graph::{self, BasicCoverageBlock}; use itertools::Itertools; @@ -551,108 +550,3 @@ fn test_covgraph_switchint_loop_then_inner_loop_else_break() { assert_successors(&basic_coverage_blocks, bcb(5), &[bcb(1)]); assert_successors(&basic_coverage_blocks, bcb(6), &[bcb(4)]); } - -#[test] -fn test_find_loop_backedges_none() { - let mir_body = goto_switchint(); - let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - if false { - eprintln!( - "basic_coverage_blocks = {:?}", - basic_coverage_blocks.iter_enumerated().collect::>() - ); - eprintln!("successors = {:?}", basic_coverage_blocks.successors); - } - let backedges = graph::find_loop_backedges(&basic_coverage_blocks); - assert_eq!( - backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::(), - 0, - "backedges: {:?}", - backedges - ); -} - -#[test] -fn test_find_loop_backedges_one() { - let mir_body = switchint_then_loop_else_return(); - let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - let backedges = graph::find_loop_backedges(&basic_coverage_blocks); - assert_eq!( - backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::(), - 1, - "backedges: {:?}", - backedges - ); - - assert_eq!(backedges[bcb(1)], &[bcb(3)]); -} - -#[test] -fn test_find_loop_backedges_two() { - let mir_body = switchint_loop_then_inner_loop_else_break(); - let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - let backedges = graph::find_loop_backedges(&basic_coverage_blocks); - assert_eq!( - backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::(), - 2, - "backedges: {:?}", - backedges - ); - - assert_eq!(backedges[bcb(1)], &[bcb(5)]); - assert_eq!(backedges[bcb(4)], &[bcb(6)]); -} - -#[test] -fn test_traverse_coverage_with_loops() { - let mir_body = switchint_loop_then_inner_loop_else_break(); - let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - let mut traversed_in_order = Vec::new(); - let mut traversal = graph::TraverseCoverageGraphWithLoops::new(&basic_coverage_blocks); - while let Some(bcb) = traversal.next() { - traversed_in_order.push(bcb); - } - - // bcb0 is visited first. Then bcb1 starts the first loop, and all remaining nodes, *except* - // bcb6 are inside the first loop. - assert_eq!( - *traversed_in_order.last().expect("should have elements"), - bcb(6), - "bcb6 should not be visited until all nodes inside the first loop have been visited" - ); -} - -#[test] -fn test_make_bcb_counters() { - rustc_span::create_default_session_globals_then(|| { - let mir_body = goto_switchint(); - let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - // Historically this test would use `spans` internals to set up fake - // coverage spans for BCBs 1 and 2. Now we skip that step and just tell - // BCB counter construction that those BCBs have spans. - let bcb_has_coverage_spans = |bcb: BasicCoverageBlock| (1..=2).contains(&bcb.as_usize()); - let coverage_counters = counters::CoverageCounters::make_bcb_counters( - &basic_coverage_blocks, - bcb_has_coverage_spans, - ); - assert_eq!(coverage_counters.num_expressions(), 0); - - assert_eq!( - 0, // bcb1 has a `Counter` with id = 0 - match coverage_counters.bcb_counter(bcb(1)).expect("should have a counter") { - counters::BcbCounter::Counter { id, .. } => id, - _ => panic!("expected a Counter"), - } - .as_u32() - ); - - assert_eq!( - 1, // bcb2 has a `Counter` with id = 1 - match coverage_counters.bcb_counter(bcb(2)).expect("should have a counter") { - counters::BcbCounter::Counter { id, .. } => id, - _ => panic!("expected a Counter"), - } - .as_u32() - ); - }); -} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 2cbe0a01e9ec..d04bb8d302e2 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -10,7 +10,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs} use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -293,7 +293,7 @@ impl<'tcx> Inliner<'tcx> { } match callee.def { - InstanceDef::Item(_) => { + InstanceKind::Item(_) => { // If there is no MIR available (either because it was not in metadata or // because it has no MIR because it's an extern function), then the inliner // won't cause cycles on this. @@ -302,24 +302,24 @@ impl<'tcx> Inliner<'tcx> { } } // These have no own callable MIR. - InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => { + InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => { return Err("instance without MIR (intrinsic / virtual)"); } // This cannot result in an immediate cycle since the callee MIR is a shim, which does // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we // do not need to catch this here, we can wait until the inliner decides to continue // inlining a second time. - InstanceDef::VTableShim(_) - | InstanceDef::ReifyShim(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineKindShim { .. } - | InstanceDef::DropGlue(..) - | InstanceDef::CloneShim(..) - | InstanceDef::ThreadLocalShim(..) - | InstanceDef::FnPtrAddrShim(..) - | InstanceDef::AsyncDropGlueCtorShim(..) => return Ok(()), + InstanceKind::VTableShim(_) + | InstanceKind::ReifyShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::CoroutineKindShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::CloneShim(..) + | InstanceKind::ThreadLocalShim(..) + | InstanceKind::FnPtrAddrShim(..) + | InstanceKind::AsyncDropGlueCtorShim(..) => return Ok(()), } if self.tcx.is_constructor(callee_def_id) { @@ -372,7 +372,7 @@ impl<'tcx> Inliner<'tcx> { let callee = Instance::resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?; - if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def { + if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def { return None; } @@ -384,7 +384,7 @@ impl<'tcx> Inliner<'tcx> { // Additionally, check that the body that we're inlining actually agrees // with the ABI of the trait that the item comes from. - if let InstanceDef::Item(instance_def_id) = callee.def + if let InstanceKind::Item(instance_def_id) = callee.def && self.tcx.def_kind(instance_def_id) == DefKind::AssocFn && let instance_fn_sig = self.tcx.fn_sig(instance_def_id).skip_binder() && instance_fn_sig.abi() != fn_sig.abi() @@ -1063,10 +1063,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { #[instrument(skip(tcx), level = "debug")] fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, - instance: InstanceDef<'tcx>, + instance: InstanceKind<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - if let ty::InstanceDef::DropGlue(_, Some(ty)) - | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) = instance + if let ty::InstanceKind::DropGlue(_, Some(ty)) + | ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) = instance && let ty::Adt(def, args) = ty.kind() { let fields = def.all_fields(); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 8c5f965108bd..35bcd24ce95b 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -3,7 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, GenericArgsRef, InstanceDef, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt}; use rustc_session::Limit; use rustc_span::sym; @@ -22,7 +22,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( "you should not call `mir_callgraph_reachable` on immediate self recursion" ); assert!( - matches!(root.def, InstanceDef::Item(_)), + matches!(root.def, InstanceKind::Item(_)), "you should not call `mir_callgraph_reachable` on shims" ); assert!( @@ -70,7 +70,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( } match callee.def { - InstanceDef::Item(_) => { + InstanceKind::Item(_) => { // If there is no MIR available (either because it was not in metadata or // because it has no MIR because it's an extern function), then the inliner // won't cause cycles on this. @@ -80,24 +80,24 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( } } // These have no own callable MIR. - InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => continue, + InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => continue, // These have MIR and if that MIR is inlined, instantiated and then inlining is run // again, a function item can end up getting inlined. Thus we'll be able to cause // a cycle that way - InstanceDef::VTableShim(_) - | InstanceDef::ReifyShim(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineKindShim { .. } - | InstanceDef::ThreadLocalShim { .. } - | InstanceDef::CloneShim(..) => {} + InstanceKind::VTableShim(_) + | InstanceKind::ReifyShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::CoroutineKindShim { .. } + | InstanceKind::ThreadLocalShim { .. } + | InstanceKind::CloneShim(..) => {} // This shim does not call any other functions, thus there can be no recursion. - InstanceDef::FnPtrAddrShim(..) => { + InstanceKind::FnPtrAddrShim(..) => { continue; } - InstanceDef::DropGlue(..) | InstanceDef::AsyncDropGlueCtorShim(..) => { + InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) => { // FIXME: A not fully instantiated drop shim can cause ICEs if one attempts to // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this // needs some more analysis. @@ -151,12 +151,12 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( pub(crate) fn mir_inliner_callees<'tcx>( tcx: TyCtxt<'tcx>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, ) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { let steal; let guard; let body = match (instance, instance.def_id().as_local()) { - (InstanceDef::Item(_), Some(def_id)) => { + (InstanceKind::Item(_), Some(def_id)) => { steal = tcx.mir_promoted(def_id).0; guard = steal.borrow(); &*guard diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 3c0f4e9142b1..afba6781a703 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -398,7 +398,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & if is_fn_like { // Do not compute the mir call graph without said call graph actually being used. if pm::should_run_pass(tcx, &inline::Inline) { - tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id())); + tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id())); } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index d03c2d18c0c3..825f8957187e 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -29,16 +29,16 @@ pub fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } -fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'tcx> { +fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> { debug!("make_shim({:?})", instance); let mut result = match instance { - ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceDef::VTableShim(def_id) => { + ty::InstanceKind::Item(..) => bug!("item {:?} passed to make_shim", instance), + ty::InstanceKind::VTableShim(def_id) => { let adjustment = Adjustment::Deref { source: DerefSource::MutPtr }; build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id)) } - ty::InstanceDef::FnPtrShim(def_id, ty) => { + ty::InstanceKind::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); // Supports `Fn` or `async Fn` traits. let adjustment = match tcx @@ -58,10 +58,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' // a virtual call, or a direct call to a function for which // indirect calls must be codegen'd differently than direct ones // (such as `#[track_caller]`). - ty::InstanceDef::ReifyShim(def_id, _) => { + ty::InstanceKind::ReifyShim(def_id, _) => { build_call_shim(tcx, instance, None, CallKind::Direct(def_id)) } - ty::InstanceDef::ClosureOnceShim { call_once: _, track_caller: _ } => { + ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => { let fn_mut = tcx.require_lang_item(LangItem::FnMut, None); let call_mut = tcx .associated_items(fn_mut) @@ -73,16 +73,16 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } - ty::InstanceDef::ConstructCoroutineInClosureShim { + ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id, receiver_by_ref, } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref), - ty::InstanceDef::CoroutineKindShim { coroutine_def_id } => { + ty::InstanceKind::CoroutineKindShim { coroutine_def_id } => { return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone(); } - ty::InstanceDef::DropGlue(def_id, ty) => { + ty::InstanceKind::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { @@ -127,16 +127,16 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_drop_shim(tcx, def_id, ty) } - ty::InstanceDef::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance), - ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), - ty::InstanceDef::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty), - ty::InstanceDef::AsyncDropGlueCtorShim(def_id, ty) => { + ty::InstanceKind::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance), + ty::InstanceKind::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), + ty::InstanceKind::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty), + ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) => { async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty) } - ty::InstanceDef::Virtual(..) => { - bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) + ty::InstanceKind::Virtual(..) => { + bug!("InstanceKind::Virtual ({:?}) is for direct calls only", instance) } - ty::InstanceDef::Intrinsic(_) => { + ty::InstanceKind::Intrinsic(_) => { bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } }; @@ -240,7 +240,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) block(&mut blocks, TerminatorKind::Goto { target: return_block }); block(&mut blocks, TerminatorKind::Return); - let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty)); + let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty)); let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); @@ -392,7 +392,10 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { } } -fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'tcx> { +fn build_thread_local_shim<'tcx>( + tcx: TyCtxt<'tcx>, + instance: ty::InstanceKind<'tcx>, +) -> Body<'tcx> { let def_id = instance.def_id(); let span = tcx.def_span(def_id); @@ -472,7 +475,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { } fn into_mir(self) -> Body<'tcx> { - let source = MirSource::from_instance(ty::InstanceDef::CloneShim( + let source = MirSource::from_instance(ty::InstanceKind::CloneShim( self.def_id, self.sig.inputs_and_output[0], )); @@ -682,14 +685,14 @@ impl<'tcx> CloneShimBuilder<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, rcvr_adjustment: Option, call_kind: CallKind<'tcx>, ) -> Body<'tcx> { // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used // to instantiate into the signature of the shim. It is not necessary for users of this - // MIR body to perform further instantiations (see `InstanceDef::has_polymorphic_mir_body`). - let (sig_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance { + // MIR body to perform further instantiations (see `InstanceKind::has_polymorphic_mir_body`). + let (sig_args, untuple_args) = if let ty::InstanceKind::FnPtrShim(_, ty) = instance { let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx)); let untuple_args = sig.inputs(); @@ -741,8 +744,8 @@ fn build_call_shim<'tcx>( } // FIXME(eddyb) avoid having this snippet both here and in - // `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?). - if let ty::InstanceDef::VTableShim(..) = instance { + // `Instance::fn_sig` (introduce `InstanceKind::fn_sig`?). + if let ty::InstanceKind::VTableShim(..) = instance { // Modify fn(self, ...) to fn(self: *mut Self, ...) let mut inputs_and_output = sig.inputs_and_output.to_vec(); let self_arg = &mut inputs_and_output[0]; @@ -1007,7 +1010,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), is_cleanup: false, }; - let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty)); + let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty)); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } @@ -1087,7 +1090,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( is_cleanup: false, }; - let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim { + let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id, receiver_by_ref, }); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 41643f202851..ea4f5fca59e6 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -529,7 +529,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { last_bb.terminator = Some(Terminator { source_info, kind: TerminatorKind::Return }); - let source = MirSource::from_instance(ty::InstanceDef::AsyncDropGlueCtorShim( + let source = MirSource::from_instance(ty::InstanceKind::AsyncDropGlueCtorShim( self.def_id, self.self_ty, )); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ea23bbc2a38e..2cca1a6f507b 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ - self, CoroutineArgsExt, InstanceDef, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, + self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance, }; use rustc_middle::{bug, span_bug}; @@ -44,7 +44,7 @@ impl<'tcx> MirPass<'tcx> for Validator { // terribly important that they pass the validator. However, I think other passes might // still see them, in which case they might be surprised. It would probably be better if we // didn't put this through the MIR pipeline at all. - if matches!(body.source.instance, InstanceDef::Intrinsic(..) | InstanceDef::Virtual(..)) { + if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) { return; } let def_id = body.source.def_id(); @@ -95,7 +95,7 @@ impl<'tcx> MirPass<'tcx> for Validator { } if let MirPhase::Runtime(_) = body.phase { - if let ty::InstanceDef::Item(_) = body.source.instance { + if let ty::InstanceKind::Item(_) = body.source.instance { if body.has_free_regions() { cfg_checker.fail( Location::START, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 04de1654c1a4..235743fccc89 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -224,7 +224,7 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, + self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, VtblEntry, }; use rustc_middle::ty::{GenericArgKind, GenericArgs}; @@ -420,7 +420,7 @@ fn collect_items_rec<'tcx>( used_items.push(respan( starting_item.span, MonoItem::Fn(Instance { - def: InstanceDef::ThreadLocalShim(def_id), + def: InstanceKind::ThreadLocalShim(def_id), args: GenericArgs::empty(), }), )); @@ -938,7 +938,7 @@ fn visit_instance_use<'tcx>( if !should_codegen_locally(tcx, instance) { return; } - if let ty::InstanceDef::Intrinsic(def_id) = instance.def { + if let ty::InstanceKind::Intrinsic(def_id) = instance.def { let name = tcx.item_name(def_id); if let Some(_requirement) = ValidityRequirement::from_intrinsic(name) { // The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will @@ -960,31 +960,31 @@ fn visit_instance_use<'tcx>( } match instance.def { - ty::InstanceDef::Virtual(..) | ty::InstanceDef::Intrinsic(_) => { + ty::InstanceKind::Virtual(..) | ty::InstanceKind::Intrinsic(_) => { if !is_direct_call { bug!("{:?} being reified", instance); } } - ty::InstanceDef::ThreadLocalShim(..) => { + ty::InstanceKind::ThreadLocalShim(..) => { bug!("{:?} being reified", instance); } - ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => { + ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => { // Don't need to emit noop drop glue if we are calling directly. if !is_direct_call { output.push(create_fn_mono_item(tcx, instance, source)); } } - ty::InstanceDef::DropGlue(_, Some(_)) - | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) - | ty::InstanceDef::VTableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | ty::InstanceDef::Item(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::CloneShim(..) - | ty::InstanceDef::FnPtrAddrShim(..) => { + ty::InstanceKind::DropGlue(_, Some(_)) + | ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) + | ty::InstanceKind::VTableShim(..) + | ty::InstanceKind::ReifyShim(..) + | ty::InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | ty::InstanceKind::Item(..) + | ty::InstanceKind::FnPtrShim(..) + | ty::InstanceKind::CloneShim(..) + | ty::InstanceKind::FnPtrAddrShim(..) => { output.push(create_fn_mono_item(tcx, instance, source)); } } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 14b5b22dc648..9a7c488833a1 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -114,7 +114,7 @@ use rustc_middle::mir::mono::{ }; use rustc_middle::query::Providers; use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths}; -use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt}; +use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceKind, TyCtxt}; use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_session::CodegenUnits; use rustc_span::symbol::Symbol; @@ -620,20 +620,20 @@ fn characteristic_def_id_of_mono_item<'tcx>( match mono_item { MonoItem::Fn(instance) => { let def_id = match instance.def { - ty::InstanceDef::Item(def) => def, - ty::InstanceDef::VTableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | ty::InstanceDef::Intrinsic(..) - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::Virtual(..) - | ty::InstanceDef::CloneShim(..) - | ty::InstanceDef::ThreadLocalShim(..) - | ty::InstanceDef::FnPtrAddrShim(..) - | ty::InstanceDef::AsyncDropGlueCtorShim(..) => return None, + ty::InstanceKind::Item(def) => def, + ty::InstanceKind::VTableShim(..) + | ty::InstanceKind::ReifyShim(..) + | ty::InstanceKind::FnPtrShim(..) + | ty::InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | ty::InstanceKind::Intrinsic(..) + | ty::InstanceKind::DropGlue(..) + | ty::InstanceKind::Virtual(..) + | ty::InstanceKind::CloneShim(..) + | ty::InstanceKind::ThreadLocalShim(..) + | ty::InstanceKind::FnPtrAddrShim(..) + | ty::InstanceKind::AsyncDropGlueCtorShim(..) => return None, }; // If this is a method, we want to put it into the same module as @@ -777,28 +777,28 @@ fn mono_item_visibility<'tcx>( }; let def_id = match instance.def { - InstanceDef::Item(def_id) - | InstanceDef::DropGlue(def_id, Some(_)) - | InstanceDef::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id, + InstanceKind::Item(def_id) + | InstanceKind::DropGlue(def_id, Some(_)) + | InstanceKind::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id, // We match the visibility of statics here - InstanceDef::ThreadLocalShim(def_id) => { + InstanceKind::ThreadLocalShim(def_id) => { return static_visibility(tcx, can_be_internalized, def_id); } // These are all compiler glue and such, never exported, always hidden. - InstanceDef::VTableShim(..) - | InstanceDef::ReifyShim(..) - | InstanceDef::FnPtrShim(..) - | InstanceDef::Virtual(..) - | InstanceDef::Intrinsic(..) - | InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineKindShim { .. } - | InstanceDef::DropGlue(..) - | InstanceDef::AsyncDropGlueCtorShim(..) - | InstanceDef::CloneShim(..) - | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, + InstanceKind::VTableShim(..) + | InstanceKind::ReifyShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::Intrinsic(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::CoroutineKindShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::AsyncDropGlueCtorShim(..) + | InstanceKind::CloneShim(..) + | InstanceKind::FnPtrAddrShim(..) => return Visibility::Hidden, }; // The `start_fn` lang item is actually a monomorphized instance of a @@ -813,7 +813,7 @@ fn mono_item_visibility<'tcx>( // internalization, but we have to understand that it's referenced // from the `main` symbol we'll generate later. // - // This may be fixable with a new `InstanceDef` perhaps? Unsure! + // This may be fixable with a new `InstanceKind` perhaps? Unsure! if tcx.is_lang_item(def_id, LangItem::Start) { *can_be_internalized = false; return Visibility::Hidden; diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index c187cb63ee18..2d69bfa4da8e 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -33,7 +33,7 @@ pub fn provide(providers: &mut Providers) { /// parameters are used). fn unused_generic_params<'tcx>( tcx: TyCtxt<'tcx>, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, ) -> UnusedGenericParams { assert!(instance.def_id().is_local()); @@ -88,7 +88,7 @@ fn unused_generic_params<'tcx>( fn should_polymorphize<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - instance: ty::InstanceDef<'tcx>, + instance: ty::InstanceKind<'tcx>, ) -> bool { // If an instance's MIR body is not polymorphic then the modified generic parameters that are // derived from polymorphization's result won't make any difference. @@ -97,7 +97,7 @@ fn should_polymorphize<'tcx>( } // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic. - if matches!(instance, ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::Virtual(..)) { + if matches!(instance, ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::Virtual(..)) { return false; } @@ -230,7 +230,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { /// a closure, coroutine or constant). #[instrument(level = "debug", skip(self, def_id, args))] fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) { - let instance = ty::InstanceDef::Item(def_id); + let instance = ty::InstanceKind::Item(def_id); let unused = self.tcx.unused_generic_params(instance); debug!(?self.unused_parameters, ?unused); for (i, arg) in args.iter().enumerate() { diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index b913a05095c2..144caf36ee53 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -1,3 +1,9 @@ +//! Crate containing the implementation of the next-generation trait solver. +//! +//! This crate may also contain things that are used by the old trait solver, +//! but were uplifted in the process of making the new trait solver generic. +//! So if you got to this crate from the old solver, it's totally normal. + pub mod canonicalizer; pub mod resolve; pub mod solve; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index fb57d42f6df1..d37056269385 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -973,8 +973,12 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { fn visit_nested_body(&mut self, body_id: hir::BodyId) { - let old_maybe_typeck_results = - self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id)); + let new_typeck_results = self.tcx.typeck_body(body_id); + // Do not try reporting privacy violations if we failed to infer types. + if new_typeck_results.tainted_by_errors.is_some() { + return; + } + let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results); self.visit_body(self.tcx.hir().body(body_id)); self.maybe_typeck_results = old_maybe_typeck_results; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index b6a23317dc99..7d531385e212 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -966,7 +966,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for single_import in &resolution.single_imports { let Some(import_vis) = single_import.vis.get() else { // This branch handles a cycle in single imports, which occurs - // when we've previously captured the `vis` value during an import + // when we've previously **steal** the `vis` value during an import // process. // // For example: @@ -998,21 +998,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; - let ImportKind::Single { source: ident, target, target_bindings, .. } = - &single_import.kind + let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind else { unreachable!(); }; - if (ident != target) && target_bindings.iter().all(|binding| binding.get().is_none()) { + if source != target { // This branch allows the binding to be defined or updated later if the target name - // can hide the source but these bindings are not obtained. - // avoiding module inconsistency between the resolve process and the finalize process. - // See more details in #124840 - return Err((Undetermined, Weak::No)); + // can hide the source. + if target_bindings.iter().all(|binding| binding.get().is_none()) { + // None of the target bindings are available, so we can't determine + // if this binding is correct or not. + // See more details in #124840 + return Err((Undetermined, Weak::No)); + } else if target_bindings[ns].get().is_none() && binding.is_some() { + // `binding.is_some()` avoids the condition where the binding + // truly doesn't exist in this namespace and should return `Err(Determined)`. + return Err((Undetermined, Weak::No)); + } } + match self.resolve_ident_in_module( module, - *ident, + *source, ns, &single_import.parent_scope, None, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fa711d932b63..c1e83c59f98c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -310,9 +310,10 @@ enum LifetimeRibKind { /// error on default object bounds (e.g., `Box`). AnonymousReportError, - /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior - /// is a bug and will be reverted soon. - AnonymousWarn(NodeId), + /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope, + /// otherwise give a warning that the previous behavior of introducing a new early-bound + /// lifetime is a bug and will be removed (if `emit_lint` is enabled). + StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool }, /// Signal we cannot find which should be the anonymous lifetime. ElisionFailure, @@ -1212,7 +1213,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } LifetimeRibKind::AnonymousCreateParameter { .. } | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarn(_) + | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } | LifetimeRibKind::Elided(_) | LifetimeRibKind::ElisionFailure | LifetimeRibKind::ConcreteAnonConst(_) @@ -1580,7 +1581,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // lifetime would be illegal. LifetimeRibKind::Item | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarn(_) + | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many), // An anonymous lifetime is legal here, and bound to the right // place, go ahead. @@ -1643,7 +1644,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ElisionFailure | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarn(_) => {} + | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {} } } @@ -1677,16 +1678,36 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } - LifetimeRibKind::AnonymousWarn(node_id) => { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, - node_id, - lifetime.ident.span, - lint::BuiltinLintDiag::AssociatedConstElidedLifetime { - elided, - span: lifetime.ident.span, - }, - ); + LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => { + let mut lifetimes_in_scope = vec![]; + for rib in &self.lifetime_ribs[..i] { + lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span)); + // Consider any anonymous lifetimes, too + if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind + && let Some(extra) = self.r.extra_lifetime_params_map.get(&binder) + { + lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span)); + } + } + if lifetimes_in_scope.is_empty() { + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Static, + elision_candidate, + ); + return; + } else if emit_lint { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, + node_id, + lifetime.ident.span, + lint::BuiltinLintDiag::AssociatedConstElidedLifetime { + elided, + span: lifetime.ident.span, + lifetimes_in_scope: lifetimes_in_scope.into(), + }, + ); + } } LifetimeRibKind::AnonymousReportError => { if elided { @@ -1904,7 +1925,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } - | LifetimeRibKind::AnonymousWarn(_) => { + | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => { let sess = self.r.tcx.sess; let subdiag = rustc_errors::elided_lifetime_in_path_suggestion( sess.source_map(), @@ -2838,19 +2859,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { kind: LifetimeBinderKind::ConstItem, }, |this| { - this.visit_generics(generics); - this.visit_ty(ty); + this.with_lifetime_rib( + LifetimeRibKind::StaticIfNoLifetimeInScope { + lint_id: item.id, + emit_lint: false, + }, + |this| { + this.visit_generics(generics); + this.visit_ty(ty); - // Only impose the restrictions of `ConstRibKind` for an - // actual constant expression in a provided default. - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } + // Only impose the restrictions of `ConstRibKind` for an + // actual constant expression in a provided default. + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }, + ) }, ); } @@ -3030,30 +3059,37 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { kind: LifetimeBinderKind::ConstItem, }, |this| { - this.with_lifetime_rib(LifetimeRibKind::AnonymousWarn(item.id), |this| { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + this.with_lifetime_rib( + LifetimeRibKind::StaticIfNoLifetimeInScope { + lint_id: item.id, + // In impls, it's not a hard error yet due to backcompat. + emit_lint: true, + }, + |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - this.visit_generics(generics); - this.visit_ty(ty); - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } - }); + this.visit_generics(generics); + this.visit_ty(ty); + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }, + ); }, ); } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 2cb0c06e3361..832efb119992 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -288,9 +288,9 @@ pub fn transform_instance<'tcx>( mut instance: Instance<'tcx>, options: TransformTyOptions, ) -> Instance<'tcx> { - if (matches!(instance.def, ty::InstanceDef::Virtual(..)) + if (matches!(instance.def, ty::InstanceKind::Virtual(..)) && tcx.is_lang_item(instance.def_id(), LangItem::DropInPlace)) - || matches!(instance.def, ty::InstanceDef::DropGlue(..)) + || matches!(instance.def, ty::InstanceKind::DropGlue(..)) { // Adjust the type ids of DropGlues // @@ -316,7 +316,7 @@ pub fn transform_instance<'tcx>( let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]); let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn); instance.args = tcx.mk_args_trait(self_ty, List::empty()); - } else if let ty::InstanceDef::Virtual(def_id, _) = instance.def { + } else if let ty::InstanceKind::Virtual(def_id, _) = instance.def { // Transform self into a trait object of the trait that defines the method for virtual // functions to match the type erasure done below. let upcast_ty = match tcx.trait_of_item(def_id) { @@ -343,7 +343,7 @@ pub fn transform_instance<'tcx>( tcx.types.unit }; instance.args = tcx.mk_args_trait(self_ty, instance.args.into_iter().skip(1)); - } else if let ty::InstanceDef::VTableShim(def_id) = instance.def + } else if let ty::InstanceKind::VTableShim(def_id) = instance.def && let Some(trait_id) = tcx.trait_of_item(def_id) { // Adjust the type ids of VTableShims to the type id expected in the call sites for the @@ -387,7 +387,7 @@ pub fn transform_instance<'tcx>( // If we ever *do* start encoding the vtable index, we will need to generate an alias set // based on which vtables we are putting this method into, as there will be more than one // index value when supertraits are involved. - instance.def = ty::InstanceDef::Virtual(method_id, 0); + instance.def = ty::InstanceKind::Virtual(method_id, 0); let abstract_trait_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args); @@ -442,7 +442,7 @@ pub fn transform_instance<'tcx>( .expect("No call-family function on closure-like Fn trait?") .def_id; - instance.def = ty::InstanceDef::Virtual(call, 0); + instance.def = ty::InstanceKind::Virtual(call, 0); instance.args = abstract_args; } } diff --git a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs index 436c398e39b0..651ba6124696 100644 --- a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs +++ b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs @@ -3,7 +3,7 @@ //! //! For more information about LLVM KCFI and cross-language LLVM KCFI support for the Rust compiler, //! see the tracking issue #123479. -use rustc_middle::ty::{Instance, InstanceDef, ReifyReason, Ty, TyCtxt}; +use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt}; use rustc_target::abi::call::FnAbi; use std::hash::Hasher; use twox_hash::XxHash64; @@ -44,7 +44,7 @@ pub fn typeid_for_instance<'tcx>( // // This was implemented for KCFI support in #123106 and #123052 (which introduced the // ReifyReason). The tracking issue for KCFI support for Rust is #123479. - if matches!(instance.def, InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr))) { + if matches!(instance.def, InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr))) { options.insert(TypeIdOptions::USE_CONCRETE_SELF); } // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index 577373cbc958..42fa6989ddcf 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -19,7 +19,7 @@ impl<'tcx> BodyBuilder<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self { let instance = match instance.def { // To get the fallback body of an intrinsic, we need to convert it to an item. - ty::InstanceDef::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args), + ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args), _ => instance, }; BodyBuilder { tcx, instance } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 4348bc31bf9e..9afd507ce113 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -60,7 +60,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body { let mut tables = self.0.borrow_mut(); let def_id = tables[item]; - tables.tcx.instance_mir(rustc_middle::ty::InstanceDef::Item(def_id)).stable(&mut tables) + tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables) } fn has_body(&self, def: DefId) -> bool { @@ -548,13 +548,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { let tables = self.0.borrow_mut(); let instance = tables.instances[def]; - matches!(instance.def, ty::InstanceDef::DropGlue(_, None)) + matches!(instance.def, ty::InstanceKind::DropGlue(_, None)) } fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool { let tables = self.0.borrow_mut(); let instance = tables.instances[def]; - matches!(instance.def, ty::InstanceDef::AsyncDropGlueCtorShim(_, None)) + matches!(instance.def, ty::InstanceKind::AsyncDropGlueCtorShim(_, None)) } fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index e3cd7187e773..9cd841bba109 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -839,22 +839,22 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let def = tables.instance_def(tables.tcx.lift(*self).unwrap()); let kind = match self.def { - ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item, - ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, - ty::InstanceDef::Virtual(_def_id, idx) => { + ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item, + ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, + ty::InstanceKind::Virtual(_def_id, idx) => { stable_mir::mir::mono::InstanceKind::Virtual { idx } } - ty::InstanceDef::VTableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::FnPtrAddrShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } - | ty::InstanceDef::ThreadLocalShim(..) - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::CloneShim(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::AsyncDropGlueCtorShim(..) => { + ty::InstanceKind::VTableShim(..) + | ty::InstanceKind::ReifyShim(..) + | ty::InstanceKind::FnPtrAddrShim(..) + | ty::InstanceKind::ClosureOnceShim { .. } + | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } + | ty::InstanceKind::ThreadLocalShim(..) + | ty::InstanceKind::DropGlue(..) + | ty::InstanceKind::CloneShim(..) + | ty::InstanceKind::FnPtrShim(..) + | ty::InstanceKind::AsyncDropGlueCtorShim(..) => { stable_mir::mir::mono::InstanceKind::Shim } }; diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 89f9adfcfd66..82522e995d63 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -60,9 +60,9 @@ impl<'tcx> Tables<'tcx> { self.item_has_body(def_id) || !matches!( instance.def, - ty::InstanceDef::Virtual(..) - | ty::InstanceDef::Intrinsic(..) - | ty::InstanceDef::Item(..) + ty::InstanceKind::Virtual(..) + | ty::InstanceKind::Intrinsic(..) + | ty::InstanceKind::Item(..) ) } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 75cac6c7992a..9edd2ff9b1a5 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -56,8 +56,8 @@ pub(super) fn mangle<'tcx>( printer .print_def_path( def_id, - if let ty::InstanceDef::DropGlue(_, _) | ty::InstanceDef::AsyncDropGlueCtorShim(_, _) = - instance.def + if let ty::InstanceKind::DropGlue(_, _) + | ty::InstanceKind::AsyncDropGlueCtorShim(_, _) = instance.def { // Add the name of the dropped type to the symbol name &*instance.args @@ -68,13 +68,13 @@ pub(super) fn mangle<'tcx>( .unwrap(); match instance.def { - ty::InstanceDef::ThreadLocalShim(..) => { + ty::InstanceKind::ThreadLocalShim(..) => { printer.write_str("{{tls-shim}}").unwrap(); } - ty::InstanceDef::VTableShim(..) => { + ty::InstanceKind::VTableShim(..) => { printer.write_str("{{vtable-shim}}").unwrap(); } - ty::InstanceDef::ReifyShim(_, reason) => { + ty::InstanceKind::ReifyShim(_, reason) => { printer.write_str("{{reify-shim").unwrap(); match reason { Some(ReifyReason::FnPtr) => printer.write_str("-fnptr").unwrap(), @@ -85,8 +85,8 @@ pub(super) fn mangle<'tcx>( } // FIXME(async_closures): This shouldn't be needed when we fix // `Instance::ty`/`Instance::def_id`. - ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } => { + ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } => { printer.write_str("{{fn-once-shim}}").unwrap(); } _ => {} diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 55479bce6fc8..42c4fa83d1bf 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -43,14 +43,14 @@ pub(super) fn mangle<'tcx>( // Append `::{shim:...#0}` to shims that can coexist with a non-shim instance. let shim_kind = match instance.def { - ty::InstanceDef::ThreadLocalShim(_) => Some("tls"), - ty::InstanceDef::VTableShim(_) => Some("vtable"), - ty::InstanceDef::ReifyShim(_, None) => Some("reify"), - ty::InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr)) => Some("reify_fnptr"), - ty::InstanceDef::ReifyShim(_, Some(ReifyReason::Vtable)) => Some("reify_vtable"), + ty::InstanceKind::ThreadLocalShim(_) => Some("tls"), + ty::InstanceKind::VTableShim(_) => Some("vtable"), + ty::InstanceKind::ReifyShim(_, None) => Some("reify"), + ty::InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => Some("reify_fnptr"), + ty::InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => Some("reify_vtable"), - ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineKindShim { .. } => Some("fn_once"), + ty::InstanceKind::ConstructCoroutineInClosureShim { .. } + | ty::InstanceKind::CoroutineKindShim { .. } => Some("fn_once"), _ => None, }; diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 0e0b9e983391..b5753d60f599 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -135,8 +135,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { // Remove any trivial region constraints once we've resolved regions external_constraints .region_constraints - .outlives - .retain(|(outlives, _)| outlives.0.as_region().map_or(true, |re| re != outlives.1)); + .retain(|outlives| outlives.0.as_region().map_or(true, |re| re != outlives.1)); let canonical = Canonicalizer::canonicalize( self.infcx, @@ -179,8 +178,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { fn compute_external_query_constraints( &self, certainty: Certainty, - normalization_nested_goals: NestedNormalizationGoals<'tcx>, - ) -> ExternalConstraintsData<'tcx> { + normalization_nested_goals: NestedNormalizationGoals>, + ) -> ExternalConstraintsData> { // We only return region constraints once the certainty is `Yes`. This // is necessary as we may drop nested goals on ambiguity, which may result // in unconstrained inference variables in the region constraints. It also @@ -193,30 +192,40 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { // Cannot use `take_registered_region_obligations` as we may compute the response // inside of a `probe` whenever we have multiple choices inside of the solver. let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); - let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.interner(), - region_obligations.iter().map(|r_o| { - (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()) - }), - region_constraints, - ) - }); - + let QueryRegionConstraints { outlives, member_constraints } = + self.infcx.with_region_constraints(|region_constraints| { + make_query_region_constraints( + self.interner(), + region_obligations.iter().map(|r_o| { + (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()) + }), + region_constraints, + ) + }); + assert_eq!(member_constraints, vec![]); let mut seen = FxHashSet::default(); - region_constraints.outlives.retain(|outlives| seen.insert(*outlives)); - region_constraints + outlives + .into_iter() + .filter(|(outlives, _)| seen.insert(*outlives)) + .map(|(outlives, _origin)| outlives) + .collect() } else { Default::default() }; - let mut opaque_types = self.infcx.clone_opaque_types_for_query_response(); - // Only return opaque type keys for newly-defined opaques - opaque_types.retain(|(a, _)| { - self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) - }); - - ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } + ExternalConstraintsData { + region_constraints, + opaque_types: self + .infcx + .clone_opaque_types_for_query_response() + .into_iter() + // Only return *newly defined* opaque types. + .filter(|(a, _)| { + self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) + }) + .collect(), + normalization_nested_goals, + } } /// After calling a canonical query, we apply the constraints returned @@ -232,7 +241,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { param_env: ty::ParamEnv<'tcx>, original_values: Vec>, response: CanonicalResponse<'tcx>, - ) -> (NestedNormalizationGoals<'tcx>, Certainty) { + ) -> (NestedNormalizationGoals>, Certainty) { let instantiation = Self::compute_query_response_instantiation_values( self.infcx, &original_values, @@ -369,16 +378,17 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { } } - fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) { - for &(ty::OutlivesPredicate(lhs, rhs), _) in ®ion_constraints.outlives { + fn register_region_constraints( + &mut self, + outlives: &[ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>], + ) { + for &ty::OutlivesPredicate(lhs, rhs) in outlives { match lhs.unpack() { GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs), GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs), GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"), } } - - assert!(region_constraints.member_constraints.is_empty()); } fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) { diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 6b8375b53e8f..74938d2bbd70 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -29,11 +29,9 @@ use super::inspect::ProofTreeBuilder; use super::{search_graph, GoalEvaluationKind, FIXPOINT_STEP_LIMIT}; use super::{search_graph::SearchGraph, Goal}; use super::{GoalSource, SolverMode}; -pub use select::InferCtxtSelectExt; pub(super) mod canonical; mod probe; -mod select; pub struct EvalCtxt<'a, Infcx, I = ::Interner> where @@ -339,7 +337,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, goal: Goal<'tcx, ty::Predicate<'tcx>>, - ) -> Result<(NestedNormalizationGoals<'tcx>, bool, Certainty), NoSolution> { + ) -> Result<(NestedNormalizationGoals>, bool, Certainty), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); @@ -382,7 +380,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { param_env: ty::ParamEnv<'tcx>, original_values: Vec>, response: CanonicalResponse<'tcx>, - ) -> (NestedNormalizationGoals<'tcx>, Certainty, bool) { + ) -> (NestedNormalizationGoals>, Certainty, bool) { if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty { return (NestedNormalizationGoals::empty(), response.value.certainty, false); } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index fdcf4ff11e46..4f1be5cbc853 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -37,12 +37,14 @@ mod normalize; mod normalizes_to; mod project_goals; mod search_graph; +mod select; mod trait_goals; -pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt}; +pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt}; pub use fulfill::{FulfillmentCtxt, NextSolverError}; pub(crate) use normalize::deeply_normalize_for_diagnostics; pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes}; +pub use select::InferCtxtSelectExt; /// How many fixpoint iterations we should attempt inside of the solver before bailing /// with overflow. diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 60a15392e0be..5c5923e9d396 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -10,13 +10,13 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::MaybeCause; use rustc_infer::traits::Reveal; +use rustc_middle::bug; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::NormalizesTo; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeVisitableExt, Upcast}; -use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; mod anon_const; @@ -200,14 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| { let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason); - let error_term = match assoc_def.item.kind { - ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(), - ty::AssocKind::Type => Ty::new_error(tcx, guar).into(), - // This makes no sense... - ty::AssocKind::Fn => span_bug!( - tcx.def_span(assoc_def.item.def_id), - "cannot project to an associated function" - ), + let error_term = match goal.predicate.alias.kind(tcx) { + ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(), + ty::AliasTermKind::ProjectionConst => ty::Const::new_error(tcx, guar).into(), + kind => bug!("expected projection, found {kind:?}"), }; ecx.instantiate_normalizes_to_term(goal, error_term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -238,9 +234,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } // Finally we construct the actual value of the associated type. - let term = match assoc_def.item.kind { - ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()), - ty::AssocKind::Const => { + let term = match goal.predicate.alias.kind(tcx) { + ty::AliasTermKind::ProjectionTy => { + tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()) + } + ty::AliasTermKind::ProjectionConst => { if tcx.features().associated_const_equality { bug!("associated const projection is not supported yet") } else { @@ -254,7 +252,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ) } } - ty::AssocKind::Fn => unreachable!("we should never project to a fn"), + kind => bug!("expected projection, found {kind:?}"), }; ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, associated_item_args)); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs similarity index 100% rename from compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs rename to compiler/rustc_trait_selection/src/solve/select.rs diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c5ea85c90dc5..f1dd94839fe1 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -5,7 +5,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout, }; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; +use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::def_id::DefId; use rustc_target::abi::call::{ @@ -33,7 +33,7 @@ fn fn_sig_for_fn_abi<'tcx>( instance: ty::Instance<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> ty::PolyFnSig<'tcx> { - if let InstanceDef::ThreadLocalShim(..) = instance.def { + if let InstanceKind::ThreadLocalShim(..) = instance.def { return ty::Binder::dummy(tcx.mk_fn_sig( [], tcx.thread_local_ptr_ty(instance.def_id()), @@ -63,7 +63,7 @@ fn fn_sig_for_fn_abi<'tcx>( _ => unreachable!(), }; - if let ty::InstanceDef::VTableShim(..) = instance.def { + if let ty::InstanceKind::VTableShim(..) = instance.def { // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. sig = sig.map_bound(|mut sig| { let mut inputs_and_output = sig.inputs_and_output.to_vec(); @@ -121,7 +121,7 @@ fn fn_sig_for_fn_abi<'tcx>( let mut coroutine_kind = args.as_coroutine_closure().kind(); let env_ty = - if let InstanceDef::ConstructCoroutineInClosureShim { receiver_by_ref, .. } = + if let InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref, .. } = instance.def { coroutine_kind = ty::ClosureKind::FnOnce; @@ -174,7 +174,7 @@ fn fn_sig_for_fn_abi<'tcx>( // make sure we respect the `target_kind` in that shim. // FIXME(async_closures): This shouldn't be needed, and we should be populating // a separate def-id for these bodies. - if let InstanceDef::CoroutineKindShim { .. } = instance.def { + if let InstanceKind::CoroutineKindShim { .. } = instance.def { // Grab the parent coroutine-closure. It has the same args for the purposes // of instantiation, so this will be okay to do. let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx @@ -386,7 +386,7 @@ fn fn_abi_of_instance<'tcx>( extra_args, caller_location, Some(instance.def_id()), - matches!(instance.def, ty::InstanceDef::Virtual(..)), + matches!(instance.def, ty::InstanceKind::Virtual(..)), ) } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index fcd808b59464..c50a490a9dc0 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -34,7 +34,7 @@ fn resolve_instance<'tcx>( } else { let def = if tcx.intrinsic(def_id).is_some() { debug!(" => intrinsic"); - ty::InstanceDef::Intrinsic(def_id) + ty::InstanceKind::Intrinsic(def_id) } else if tcx.is_lang_item(def_id, LangItem::DropInPlace) { let ty = args.type_at(0); @@ -53,10 +53,10 @@ fn resolve_instance<'tcx>( _ => return Ok(None), } - ty::InstanceDef::DropGlue(def_id, Some(ty)) + ty::InstanceKind::DropGlue(def_id, Some(ty)) } else { debug!(" => trivial drop glue"); - ty::InstanceDef::DropGlue(def_id, None) + ty::InstanceKind::DropGlue(def_id, None) } } else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) { let ty = args.type_at(0); @@ -75,15 +75,15 @@ fn resolve_instance<'tcx>( _ => return Ok(None), } debug!(" => nontrivial async drop glue ctor"); - ty::InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)) + ty::InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty)) } else { debug!(" => trivial async drop glue ctor"); - ty::InstanceDef::AsyncDropGlueCtorShim(def_id, None) + ty::InstanceKind::AsyncDropGlueCtorShim(def_id, None) } } else { debug!(" => free item"); // FIXME(effects): we may want to erase the effect param if that is present on this item. - ty::InstanceDef::Item(def_id) + ty::InstanceKind::Item(def_id) }; Ok(Some(Instance { def, args })) @@ -226,7 +226,7 @@ fn resolve_associated_item<'tcx>( .copied() .position(|def_id| def_id == trait_item_id); offset.map(|offset| Instance { - def: ty::InstanceDef::Virtual(trait_item_id, vtable_base + offset), + def: ty::InstanceKind::Virtual(trait_item_id, vtable_base + offset), args: rcvr_args, }) } @@ -248,7 +248,7 @@ fn resolve_associated_item<'tcx>( }; Some(Instance { - def: ty::InstanceDef::CloneShim(trait_item_id, self_ty), + def: ty::InstanceKind::CloneShim(trait_item_id, self_ty), args: rcvr_args, }) } else { @@ -265,7 +265,7 @@ fn resolve_associated_item<'tcx>( return Ok(None); } Some(Instance { - def: ty::InstanceDef::FnPtrAddrShim(trait_item_id, self_ty), + def: ty::InstanceKind::FnPtrAddrShim(trait_item_id, self_ty), args: rcvr_args, }) } else { @@ -283,7 +283,7 @@ fn resolve_associated_item<'tcx>( { // 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 + // `InstanceKind::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", @@ -295,7 +295,7 @@ fn resolve_associated_item<'tcx>( Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind)) } ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), + def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), args: rcvr_args, }), ty::CoroutineClosure(coroutine_closure_def_id, args) => { @@ -308,7 +308,7 @@ fn resolve_associated_item<'tcx>( Some(Instance::new(coroutine_closure_def_id, args)) } else { Some(Instance { - def: ty::InstanceDef::ConstructCoroutineInClosureShim { + def: ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id, receiver_by_ref: target_kind != ty::ClosureKind::FnOnce, }, @@ -331,7 +331,7 @@ fn resolve_associated_item<'tcx>( // If we're computing `AsyncFnOnce` for a by-ref closure then // construct a new body that has the right return types. Some(Instance { - def: ty::InstanceDef::ConstructCoroutineInClosureShim { + def: ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id, receiver_by_ref: false, }, @@ -345,7 +345,7 @@ fn resolve_associated_item<'tcx>( Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind)) } ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), + def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), args: rcvr_args, }), _ => bug!( diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a2b71e1fc257..11c1f73fef33 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -29,6 +29,7 @@ pub trait Interner: + IrPrint> { type DefId: Copy + Debug + Hash + Eq + TypeFoldable; + type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; type AdtDef: AdtDef; type GenericArgs: GenericArgs; @@ -103,7 +104,11 @@ pub trait Interner: type GenericsOf: GenericsOf; fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf; - type VariancesOf: Copy + Debug + Deref; + type VariancesOf: Copy + + Debug + + Deref + // FIXME: This is terrible! + + IntoIterator>; fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf; // FIXME: Remove after uplifting `EarlyBinder` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 4775a0f8cbbe..ac9b2808804c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -47,6 +47,7 @@ mod flags; mod generic_arg; mod infcx; mod interner; +mod opaque_ty; mod predicate; mod predicate_kind; mod region_kind; @@ -63,6 +64,7 @@ pub use flags::*; pub use generic_arg::*; pub use infcx::InferCtxtLike; pub use interner::*; +pub use opaque_ty::*; pub use predicate::*; pub use predicate_kind::*; pub use region_kind::*; diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs new file mode 100644 index 000000000000..607370665975 --- /dev/null +++ b/compiler/rustc_type_ir/src/opaque_ty.rs @@ -0,0 +1,51 @@ +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; + +use crate::inherent::*; +use crate::{self as ty, Interner}; + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = ""), + Copy(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +pub struct OpaqueTypeKey { + pub def_id: I::LocalDefId, + pub args: I::GenericArgs, +} + +impl OpaqueTypeKey { + pub fn iter_captured_args(self, tcx: I) -> impl Iterator { + let variances = tcx.variances_of(self.def_id.into()); + std::iter::zip(self.args, variances.into_iter()).enumerate().filter_map(|(i, (arg, v))| { + match (arg.kind(), *v) { + (_, ty::Invariant) => Some((i, arg)), + (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None, + _ => panic!("unexpected opaque type arg variance"), + } + }) + } + + pub fn fold_captured_lifetime_args( + self, + tcx: I, + mut f: impl FnMut(I::Region) -> I::Region, + ) -> Self { + let Self { def_id, args } = self; + let variances = tcx.variances_of(def_id.into()); + let args = + std::iter::zip(args, variances.into_iter()).map(|(arg, v)| match (arg.kind(), *v) { + (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, + (ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(), + _ => arg, + }); + let args = tcx.mk_args_from_iter(args); + Self { def_id, args } + } +} diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 37c9532ad894..7abcc370c886 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -154,7 +154,7 @@ pub enum RegionKind { /// parameters via `tcx.liberate_late_bound_regions`. They are then treated /// the same way as `ReEarlyParam` while inside of the function. /// - /// See for + /// See for /// more info about early and late bound lifetime parameters. ReLateParam(I::LateParamRegion), diff --git a/compiler/rustc_type_ir/src/solve.rs b/compiler/rustc_type_ir/src/solve.rs index 6a89a8a4cc30..99d2fa744947 100644 --- a/compiler/rustc_type_ir/src/solve.rs +++ b/compiler/rustc_type_ir/src/solve.rs @@ -7,7 +7,55 @@ use std::hash::Hash; use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::{Canonical, CanonicalVarValues, Interner, Upcast}; +use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; + +/// Depending on the stage of compilation, we want projection to be +/// more or less conservative. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub enum Reveal { + /// At type-checking time, we refuse to project any associated + /// type that is marked `default`. Non-`default` ("final") types + /// are always projected. This is necessary in general for + /// soundness of specialization. However, we *could* allow + /// projections in fully-monomorphic cases. We choose not to, + /// because we prefer for `default type` to force the type + /// definition to be treated abstractly by any consumers of the + /// impl. Concretely, that means that the following example will + /// fail to compile: + /// + /// ```compile_fail,E0308 + /// #![feature(specialization)] + /// trait Assoc { + /// type Output; + /// } + /// + /// impl Assoc for T { + /// default type Output = bool; + /// } + /// + /// fn main() { + /// let x: <() as Assoc>::Output = true; + /// } + /// ``` + /// + /// We also do not reveal the hidden type of opaque types during + /// type-checking. + UserFacing, + + /// At codegen time, all monomorphic projections will succeed. + /// Also, `impl Trait` is normalized to the concrete type, + /// which has to be already collected by type-checking. + /// + /// NOTE: as `impl Trait`'s concrete type should *never* + /// be observable directly by the user, `Reveal::All` + /// should not be used by checks which may expose + /// type equality or type contents to the user. + /// There are some exceptions, e.g., around auto traits and + /// transmute-checking, which expose some details, but + /// not the whole concrete type of the `impl Trait`. + All, +} pub type CanonicalInput::Predicate> = Canonical>; pub type CanonicalResponse = Canonical>; @@ -206,6 +254,47 @@ pub struct Response { pub external_constraints: I::ExternalConstraints, } +/// Additional constraints returned on success. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = ""), + Default(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub struct ExternalConstraintsData { + pub region_constraints: Vec>, + pub opaque_types: Vec<(ty::OpaqueTypeKey, I::Ty)>, + pub normalization_nested_goals: NestedNormalizationGoals, +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = ""), + Default(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub struct NestedNormalizationGoals(pub Vec<(GoalSource, Goal)>); + +impl NestedNormalizationGoals { + pub fn empty() -> Self { + NestedNormalizationGoals(vec![]) + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum Certainty { diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 042a8c9925f3..150e4f3f3185 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -928,7 +928,7 @@ pub(crate) mod tags { /// An `Option` with a type tag `I`. /// /// Since this struct implements `Erased`, the type can be erased to make a dynamically typed -/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically +/// option. The type can be checked dynamically using `Tagged::tag_id` and since this is statically /// checked for the concrete type, there is some degree of type safety. #[repr(transparent)] pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option); diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs index 5c3a0a98b105..63193bbfb35e 100644 --- a/library/core/src/future/async_drop.rs +++ b/library/core/src/future/async_drop.rs @@ -1,4 +1,4 @@ -#![unstable(feature = "async_drop", issue = "none")] +#![unstable(feature = "async_drop", issue = "126482")] use crate::fmt; use crate::future::{Future, IntoFuture}; @@ -10,27 +10,27 @@ use crate::task::{ready, Context, Poll}; /// Asynchronously drops a value by running `AsyncDrop::async_drop` /// on a value and its fields recursively. -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] pub fn async_drop(value: T) -> AsyncDropOwning { AsyncDropOwning { value: MaybeUninit::new(value), dtor: None, _pinned: PhantomPinned } } /// A future returned by the [`async_drop`]. -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] pub struct AsyncDropOwning { value: MaybeUninit, dtor: Option>, _pinned: PhantomPinned, } -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] impl fmt::Debug for AsyncDropOwning { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AsyncDropOwning").finish_non_exhaustive() } } -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] impl Future for AsyncDropOwning { type Output = (); @@ -86,24 +86,24 @@ unsafe fn async_drop_in_place_raw( /// returned future stores the `to_drop` pointer and user is required /// to guarantee that dropped value doesn't move. /// -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] pub unsafe fn async_drop_in_place(to_drop: *mut T) -> AsyncDropInPlace { // SAFETY: `async_drop_in_place_raw` has the same safety requirements unsafe { AsyncDropInPlace(async_drop_in_place_raw(to_drop)) } } /// A future returned by the [`async_drop_in_place`]. -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] pub struct AsyncDropInPlace(::AsyncDestructor); -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] impl fmt::Debug for AsyncDropInPlace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AsyncDropInPlace").finish_non_exhaustive() } } -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] impl Future for AsyncDropInPlace { type Output = (); @@ -117,18 +117,18 @@ impl Future for AsyncDropInPlace { // FIXME(zetanumbers): Add same restrictions on AsyncDrop impls as // with Drop impls /// Custom code within the asynchronous destructor. -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] #[lang = "async_drop"] pub trait AsyncDrop { /// A future returned by the [`AsyncDrop::async_drop`] to be part /// of the async destructor. - #[unstable(feature = "async_drop", issue = "none")] + #[unstable(feature = "async_drop", issue = "126482")] type Dropper<'a>: Future where Self: 'a; /// Constructs the asynchronous destructor for this type. - #[unstable(feature = "async_drop", issue = "none")] + #[unstable(feature = "async_drop", issue = "126482")] fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_>; } diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 873cccc7e96f..3a1451abfa40 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -37,7 +37,7 @@ pub use ready::{ready, Ready}; #[stable(feature = "future_poll_fn", since = "1.64.0")] pub use poll_fn::{poll_fn, PollFn}; -#[unstable(feature = "async_drop", issue = "none")] +#[unstable(feature = "async_drop", issue = "126482")] pub use async_drop::{async_drop, async_drop_in_place, AsyncDrop, AsyncDropInPlace}; /// This type is needed because: diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 55bb6166f101..448894849639 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2784,8 +2784,10 @@ macro_rules! int_impl { /// /// In other words, the result is `self / rhs` rounded to the integer `q` /// such that `self >= q * rhs`. - /// If `self > 0`, this is equal to round towards zero (the default in Rust); - /// if `self < 0`, this is equal to round towards +/- infinity. + /// If `self > 0`, this is equal to rounding towards zero (the default in Rust); + /// if `self < 0`, this is equal to rounding away from zero (towards +/- infinity). + /// If `rhs > 0`, this is equal to rounding towards -infinity; + /// if `rhs < 0`, this is equal to rounding towards +infinity. /// /// # Panics /// @@ -2823,8 +2825,8 @@ macro_rules! int_impl { /// Calculates the least nonnegative remainder of `self (mod rhs)`. /// /// This is done as if by the Euclidean division algorithm -- given - /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and - /// `0 <= r < abs(rhs)`. + /// `r = self.rem_euclid(rhs)`, the result satisfies + /// `self = rhs * self.div_euclid(rhs) + r` and `0 <= r < abs(rhs)`. /// /// # Panics /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6661f6ee78b4..a8a47b69632f 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -237,7 +237,7 @@ //! pointer. For code which *does* cast a usize to a pointer, the scope of the change depends //! on exactly what you're doing. //! -//! In general you just need to make sure that if you want to convert a usize address to a +//! In general, you just need to make sure that if you want to convert a usize address to a //! pointer and then use that pointer to read/write memory, you need to keep around a pointer //! that has sufficient provenance to perform that read/write itself. In this way all of your //! casts from an address to a pointer are essentially just applying offsets/indexing. @@ -309,7 +309,7 @@ //! i.e. the usual "ZSTs are fake, do what you want" rules apply *but* this only applies //! for actual forgery (integers cast to pointers). If you borrow some struct's field //! that *happens* to be zero-sized, the resulting pointer will have provenance tied to -//! that allocation and it will still get invalidated if the allocation gets deallocated. +//! that allocation, and it will still get invalidated if the allocation gets deallocated. //! In the future we may introduce an API to make such a forged allocation explicit. //! //! * [`wrapping_offset`][] a pointer outside its provenance. This includes pointers @@ -698,7 +698,7 @@ pub const fn dangling_mut() -> *mut T { /// /// If there is no 'exposed' provenance that justifies the way this pointer will be used, /// the program has undefined behavior. In particular, the aliasing rules still apply: pointers -/// and references that have been invalidated due to aliasing accesses cannot be used any more, +/// and references that have been invalidated due to aliasing accesses cannot be used anymore, /// even if they have been exposed! /// /// Note that there is no algorithm that decides which provenance will be used. You can think of this @@ -1097,7 +1097,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun // If we end up here, it's because we're using a simple type -- like // a small power-of-two-sized thing -- or a special type with particularly // large alignment, particularly SIMD types. - // Thus we're fine just reading-and-writing it, as either it's small + // Thus, we're fine just reading-and-writing it, as either it's small // and that works well anyway or it's special and the type's author // presumably wanted things to be done in the larger chunk. @@ -1290,7 +1290,7 @@ pub const unsafe fn read(src: *const T) -> T { // provides enough information to know that this is a typed operation. // However, as of March 2023 the compiler was not capable of taking advantage - // of that information. Thus the implementation here switched to an intrinsic, + // of that information. Thus, the implementation here switched to an intrinsic, // which lowers to `_0 = *src` in MIR, to address a few issues: // // - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not @@ -1570,7 +1570,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// As a result, using `&packed.unaligned as *const FieldType` causes immediate /// *undefined behavior* in your program. /// -/// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut) +/// Instead, you must use the [`ptr::addr_of_mut!`](addr_of_mut) /// macro to create the pointer. You may use that returned pointer together with /// this function. /// diff --git a/library/std/src/os/hermit/io/mod.rs b/library/std/src/os/hermit/io/mod.rs index 524dfae0d63a..df93f63a003c 100644 --- a/library/std/src/os/hermit/io/mod.rs +++ b/library/std/src/os/hermit/io/mod.rs @@ -1,13 +1,4 @@ -#![stable(feature = "os_fd", since = "1.66.0")] +#![stable(feature = "rust1", since = "1.0.0")] -mod net; -#[path = "../../fd/owned.rs"] -mod owned; -#[path = "../../fd/raw.rs"] -mod raw; - -// Export the types and traits for the public API. -#[stable(feature = "os_fd", since = "1.66.0")] -pub use owned::*; -#[stable(feature = "os_fd", since = "1.66.0")] -pub use raw::*; +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::os::fd::*; diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index ca3584e82f91..d2a7b316b813 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -160,7 +160,7 @@ pub(crate) mod watchos; #[cfg(target_os = "xous")] pub mod xous; -#[cfg(any(unix, target_os = "wasi", doc))] +#[cfg(any(unix, target_os = "hermit", target_os = "wasi", doc))] pub mod fd; #[cfg(any(target_os = "linux", target_os = "android", doc))] diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index abf407ea91e6..449d8c128ec6 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -520,10 +520,12 @@ impl Build { return; } - // check_submodule - let checked_out_hash = - output(helpers::git(Some(&absolute_path)).args(["rev-parse", "HEAD"])); - // update_submodules + let submodule_git = || helpers::git(Some(&absolute_path)); + + // Determine commit checked out in submodule. + let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"])); + let checked_out_hash = checked_out_hash.trim_end(); + // Determine commit that the submodule *should* have. let recorded = output(helpers::git(Some(&self.src)).args(["ls-tree", "HEAD"]).arg(relative_path)); let actual_hash = recorded @@ -531,8 +533,7 @@ impl Build { .nth(2) .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); - // update_submodule - if actual_hash == checked_out_hash.trim_end() { + if actual_hash == checked_out_hash { // already checked out return; } @@ -581,26 +582,22 @@ impl Build { // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). // diff-index reports the modifications through the exit status let has_local_modifications = !self.run_cmd( - BootstrapCommand::from(helpers::git(Some(&absolute_path)).args([ - "diff-index", - "--quiet", - "HEAD", - ])) - .allow_failure() - .output_mode(match self.is_verbose() { - true => OutputMode::PrintAll, - false => OutputMode::PrintOutput, - }), + BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) + .allow_failure() + .output_mode(match self.is_verbose() { + true => OutputMode::PrintAll, + false => OutputMode::PrintOutput, + }), ); if has_local_modifications { - self.run(helpers::git(Some(&absolute_path)).args(["stash", "push"])); + self.run(submodule_git().args(["stash", "push"])); } - self.run(helpers::git(Some(&absolute_path)).args(["reset", "-q", "--hard"])); - self.run(helpers::git(Some(&absolute_path)).args(["clean", "-qdfx"])); + self.run(submodule_git().args(["reset", "-q", "--hard"])); + self.run(submodule_git().args(["clean", "-qdfx"])); if has_local_modifications { - self.run(helpers::git(Some(&absolute_path)).args(["stash", "pop"])); + self.run(submodule_git().args(["stash", "pop"])); } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 13d1346b3d9a..4b6dc45b436d 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -501,6 +501,16 @@ pub fn git(source_dir: Option<&Path>) -> Command { if let Some(source_dir) = source_dir { git.current_dir(source_dir); + // If we are running inside git (e.g. via a hook), `GIT_DIR` is set and takes precedence + // over the current dir. Un-set it to make the current dir matter. + git.env_remove("GIT_DIR"); + // Also un-set some other variables, to be on the safe side (based on cargo's + // `fetch_with_cli`). In particular un-setting `GIT_INDEX_FILE` is required to fix some odd + // misbehavior. + git.env_remove("GIT_WORK_TREE") + .env_remove("GIT_INDEX_FILE") + .env_remove("GIT_OBJECT_DIRECTORY") + .env_remove("GIT_ALTERNATE_OBJECT_DIRECTORIES"); } git diff --git a/src/doc/book b/src/doc/book index 5228bfac8267..45c1a6d69edf 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 5228bfac8267ad24659a81b92ec5417976b5edbc +Subproject commit 45c1a6d69edfd1fc91fb7504cb73958dbd09441e diff --git a/src/doc/edition-guide b/src/doc/edition-guide index bbaabbe088e2..cb58c430b4e8 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit bbaabbe088e21a81a0d9ae6757705020d5d7b416 +Subproject commit cb58c430b4e8054c2cb81d2d4434092c482a93d8 diff --git a/src/doc/reference b/src/doc/reference index 6019b76f5b28..0b805c658040 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 6019b76f5b28938565b251bbba0bf5cc5c43d863 +Subproject commit 0b805c65804019b0ac8f2fe3117afad82a6069b8 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 4840dca06cad..b1d97bd6113a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 4840dca06cadf48b305d3ce0aeafde7f80933f80 +Subproject commit b1d97bd6113aba732b2091ce093c76f2d05bb8a0 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 6a7374bd87cb..aec82168dd31 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 6a7374bd87cbac0f8be4fd4877d8186d9c313985 +Subproject commit aec82168dd3121289a194b381f56076fc789a4d2 diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index c1796cfd82a6..356d4767c7be 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -e794b0f8557c187b5909d889aa35071f81e0a4cc +c2932aaf9d20acbc9259c762f1a06f8767c6f13f diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 74e39ffd9332..313eac363372 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -57,7 +57,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), + def: ty::InstanceKind::Item(instance.def_id()), args: instance.args, })) } diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index dab18dca2ff9..f39bcfd60dfb 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -6,7 +6,7 @@ use std::path::Path; use std::process::{Command as StdCommand, ExitStatus, Output, Stdio}; use crate::drop_bomb::DropBomb; -use crate::{assert_contains, assert_not_contains, handle_failed_output}; +use crate::{assert_contains, assert_equals, assert_not_contains, handle_failed_output}; /// This is a custom command wrapper that simplifies working with commands and makes it easier to /// ensure that we check the exit status of executed processes. @@ -21,6 +21,7 @@ use crate::{assert_contains, assert_not_contains, handle_failed_output}; /// /// [`run`]: Self::run /// [`run_fail`]: Self::run_fail +/// [`run_unchecked`]: Self::run_unchecked #[derive(Debug)] pub struct Command { cmd: StdCommand, @@ -116,6 +117,15 @@ impl Command { output } + /// Run the command but do not check its exit status. + /// Only use if you explicitly don't care about the exit status. + /// Prefer to use [`Self::run`] and [`Self::run_fail`] + /// whenever possible. + #[track_caller] + pub fn run_unchecked(&mut self) -> CompletedProcess { + self.command_output() + } + #[track_caller] fn command_output(&mut self) -> CompletedProcess { self.drop_bomb.defuse(); @@ -163,41 +173,45 @@ impl CompletedProcess { self.output.status } - /// Checks that trimmed `stdout` matches trimmed `content`. + /// Checks that trimmed `stdout` matches trimmed `expected`. #[track_caller] - pub fn assert_stdout_equals>(&self, content: S) -> &Self { - assert_eq!(self.stdout_utf8().trim(), content.as_ref().trim()); + pub fn assert_stdout_equals>(&self, expected: S) -> &Self { + assert_equals(self.stdout_utf8().trim(), expected.as_ref().trim()); self } + /// Checks that `stdout` does not contain `unexpected`. #[track_caller] - pub fn assert_stdout_contains>(self, needle: S) -> Self { - assert_contains(&self.stdout_utf8(), needle.as_ref()); + pub fn assert_stdout_not_contains>(&self, unexpected: S) -> &Self { + assert_not_contains(&self.stdout_utf8(), unexpected.as_ref()); self } + /// Checks that `stdout` contains `expected`. #[track_caller] - pub fn assert_stdout_not_contains>(&self, needle: S) -> &Self { - assert_not_contains(&self.stdout_utf8(), needle.as_ref()); + pub fn assert_stdout_contains>(&self, expected: S) -> &Self { + assert_contains(&self.stdout_utf8(), expected.as_ref()); self } - /// Checks that trimmed `stderr` matches trimmed `content`. + /// Checks that trimmed `stderr` matches trimmed `expected`. #[track_caller] - pub fn assert_stderr_equals>(&self, content: S) -> &Self { - assert_eq!(self.stderr_utf8().trim(), content.as_ref().trim()); + pub fn assert_stderr_equals>(&self, expected: S) -> &Self { + assert_equals(self.stderr_utf8().trim(), expected.as_ref().trim()); self } + /// Checks that `stderr` contains `expected`. #[track_caller] - pub fn assert_stderr_contains>(&self, needle: S) -> &Self { - assert_contains(&self.stderr_utf8(), needle.as_ref()); + pub fn assert_stderr_contains>(&self, expected: S) -> &Self { + assert_contains(&self.stderr_utf8(), expected.as_ref()); self } + /// Checks that `stderr` does not contain `unexpected`. #[track_caller] - pub fn assert_stderr_not_contains>(&self, needle: S) -> &Self { - assert_not_contains(&self.stdout_utf8(), needle.as_ref()); + pub fn assert_stderr_not_contains>(&self, unexpected: S) -> &Self { + assert_not_contains(&self.stdout_utf8(), unexpected.as_ref()); self } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index ba4524c150c4..a358ae83de1b 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -214,6 +214,38 @@ pub fn cwd() -> PathBuf { env::current_dir().unwrap() } +// FIXME(Oneirical): This will no longer be required after compiletest receives the ability +// to manipulate read-only files. See https://github.com/rust-lang/rust/issues/126334 +/// Ensure that the path P is read-only while the test runs, and restore original permissions +/// at the end so compiletest can clean up. +/// This will panic on Windows if the path is a directory (as it would otherwise do nothing) +#[track_caller] +pub fn test_while_readonly, F: FnOnce() + std::panic::UnwindSafe>( + path: P, + closure: F, +) { + let path = path.as_ref(); + if is_windows() && path.is_dir() { + eprintln!("This helper function cannot be used on Windows to make directories readonly."); + eprintln!( + "See the official documentation: + https://doc.rust-lang.org/std/fs/struct.Permissions.html#method.set_readonly" + ); + panic!("`test_while_readonly` on directory detected while on Windows."); + } + let metadata = fs_wrapper::metadata(&path); + let original_perms = metadata.permissions(); + + let mut new_perms = original_perms.clone(); + new_perms.set_readonly(true); + fs_wrapper::set_permissions(&path, new_perms); + + let success = std::panic::catch_unwind(closure); + + fs_wrapper::set_permissions(&path, original_perms); + success.unwrap(); +} + /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is /// available on the platform! #[track_caller] @@ -332,6 +364,18 @@ pub fn read_dir(dir: impl AsRef, callback: F) { } } +/// Check that `actual` is equal to `expected`. Panic otherwise. +#[track_caller] +pub fn assert_equals(actual: &str, expected: &str) { + if actual != expected { + eprintln!("=== ACTUAL TEXT ==="); + eprintln!("{}", actual); + eprintln!("=== EXPECTED ==="); + eprintln!("{}", expected); + panic!("expected text was not found in actual text"); + } +} + /// Check that `haystack` contains `needle`. Panic otherwise. #[track_caller] pub fn assert_contains(haystack: &str, needle: &str) { @@ -468,6 +512,15 @@ macro_rules! impl_common_helpers { self.cmd.run_fail() } + /// Run the command but do not check its exit status. + /// Only use if you explicitly don't care about the exit status. + /// Prefer to use [`Self::run`] and [`Self::run_fail`] + /// whenever possible. + #[track_caller] + pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess { + self.cmd.run_unchecked() + } + /// Set the path where the command will be run. pub fn current_dir>(&mut self, path: P) -> &mut Self { self.cmd.current_dir(path); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index fdd0be79a4de..895798d7c1f9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -61,7 +61,6 @@ run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/foreign-rust-exceptions/Makefile run-make/glibc-staticlib-args/Makefile -run-make/inaccessible-temp-dir/Makefile run-make/include_bytes_deps/Makefile run-make/incr-add-rust-src-component/Makefile run-make/incr-foreign-head-span/Makefile @@ -74,7 +73,6 @@ run-make/invalid-library/Makefile run-make/invalid-so/Makefile run-make/invalid-staticlib/Makefile run-make/issue-107094/Makefile -run-make/issue-10971-temps-dir/Makefile run-make/issue-109934-lto-debuginfo/Makefile run-make/issue-14698/Makefile run-make/issue-15460/Makefile @@ -83,7 +81,6 @@ run-make/issue-20626/Makefile run-make/issue-22131/Makefile run-make/issue-25581/Makefile run-make/issue-26006/Makefile -run-make/issue-26092/Makefile run-make/issue-28595/Makefile run-make/issue-33329/Makefile run-make/issue-35164/Makefile @@ -109,10 +106,8 @@ run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-padding/Makefile run-make/libtest-thread-limit/Makefile -run-make/link-arg/Makefile run-make/link-args-order/Makefile run-make/link-cfg/Makefile -run-make/link-dedup/Makefile run-make/link-framework/Makefile run-make/link-path-order/Makefile run-make/linkage-attr-on-static/Makefile @@ -153,7 +148,6 @@ run-make/optimization-remarks-dir/Makefile run-make/output-filename-conflicts-with-directory/Makefile run-make/output-filename-overwrites-input/Makefile run-make/output-type-permutations/Makefile -run-make/output-with-hyphens/Makefile run-make/override-aliased-flags/Makefile run-make/overwrite-input/Makefile run-make/panic-abort-eh_frame/Makefile diff --git a/tests/codegen/error-provide.rs b/tests/codegen/error-provide.rs new file mode 100644 index 000000000000..68dd383e5cce --- /dev/null +++ b/tests/codegen/error-provide.rs @@ -0,0 +1,50 @@ +// Codegen test for #126242 + +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(error_generic_member_access)] +use std::error::Request; +use std::fmt; + +#[derive(Debug)] +struct MyBacktrace1 {} + +#[derive(Debug)] +struct MyBacktrace2 {} + +#[derive(Debug)] +struct MyBacktrace3 {} + +#[derive(Debug)] +struct MyError { + backtrace1: MyBacktrace1, + backtrace2: MyBacktrace2, + backtrace3: MyBacktrace3, + other: MyBacktrace3, +} + +impl fmt::Display for MyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Example Error") + } +} + +impl std::error::Error for MyError { + // CHECK-LABEL: @provide + #[no_mangle] + fn provide<'a>(&'a self, request: &mut Request<'a>) { + // LLVM should be able to optimize multiple .provide_* calls into a switch table + // and eliminate redundant ones, rather than compare one-by-one. + + // CHECK-NEXT: start: + // CHECK-NEXT: %[[SCRUTINEE:[^ ]+]] = load i64, ptr + // CHECK-NEXT: switch i64 %[[SCRUTINEE]], label %{{.*}} [ + // CHECK-COUNT-3: i64 {{.*}}, label %{{.*}} + // CHECK-NEXT: ] + request + .provide_ref::(&self.backtrace1) + .provide_ref::(&self.other) + .provide_ref::(&self.backtrace2) + .provide_ref::(&self.backtrace3); + } +} diff --git a/tests/crashes/126062.rs b/tests/crashes/126062.rs deleted file mode 100644 index 9f1bec1d46e4..000000000000 --- a/tests/crashes/126062.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#126062 -struct Fail(Fail); -impl Fail { - const C: () = panic!(); -} - -fn f() { - if false { - let _val = &Fail::::C; - } -} diff --git a/tests/crashes/126376.rs b/tests/crashes/126376.rs deleted file mode 100644 index 028dde6d438e..000000000000 --- a/tests/crashes/126376.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: rust-lang/rust#126376 -mod a { - pub mod b { - pub mod c { - pub trait D {} - } - } -} - -use a::*; -use e as b; -use b::c::D as e; - -fn e() {} diff --git a/tests/crashes/126385.rs b/tests/crashes/126385.rs deleted file mode 100644 index 9e74e88c1ffe..000000000000 --- a/tests/crashes/126385.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#126385 -pub struct MyStruct<'field> { - field: &'_ [u32], -} - -impl MyStruct<'_> { - pub fn _<'a>(field: &'a[u32]) -> Self { - Self{field} - } -} diff --git a/tests/crashes/126389.rs b/tests/crashes/126389.rs deleted file mode 100644 index 7aa6ecad9a31..000000000000 --- a/tests/crashes/126389.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: rust-lang/rust#126389 - -mod a { - pub mod b { - pub mod c {} - } -} - -use a::*; - -use b::c; - -use c as b; - -fn c() {} diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs index b3227b795598..d937514c2ca2 100644 --- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs +++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs @@ -12,7 +12,6 @@ fn main() { let output = rustc().input("main.rs").emit("metadata").extern_("stable", "libstable.rmeta").run(); - let version = fs_wrapper::read_to_string(source_root().join("src/version")); let expected_string = format!("stable since {}", version.trim()); output.assert_stderr_contains(expected_string); diff --git a/tests/run-make/issue-26092/blank.rs b/tests/run-make/clear-error-blank-output/blank.rs similarity index 100% rename from tests/run-make/issue-26092/blank.rs rename to tests/run-make/clear-error-blank-output/blank.rs diff --git a/tests/run-make/clear-error-blank-output/rmake.rs b/tests/run-make/clear-error-blank-output/rmake.rs new file mode 100644 index 000000000000..e0f042cf805b --- /dev/null +++ b/tests/run-make/clear-error-blank-output/rmake.rs @@ -0,0 +1,13 @@ +// When an empty output file is passed to rustc, the ensuing error message +// should be clear. However, calling file_stem on an empty path returns None, +// which, when unwrapped, causes a panic, stopping execution of rustc +// and printing an obscure message instead of reaching the helpful +// error message. This test checks that the panic does not occur. +// See https://github.com/rust-lang/rust/pull/26199 + +use run_make_support::rustc; + +fn main() { + let output = rustc().output("").stdin(b"fn main() {}").run_fail(); + output.assert_stderr_not_contains("panic"); +} diff --git a/tests/run-make/const_fn_mir/rmake.rs b/tests/run-make/const_fn_mir/rmake.rs index a4cc4299b1b0..1ba93421855d 100644 --- a/tests/run-make/const_fn_mir/rmake.rs +++ b/tests/run-make/const_fn_mir/rmake.rs @@ -1,5 +1,7 @@ // The `needs-unwind -Cpanic=abort` gives a different MIR output. +//@ needs-unwind + use run_make_support::{cwd, diff, rustc}; fn main() { diff --git a/tests/run-make/inaccessible-temp-dir/Makefile b/tests/run-make/inaccessible-temp-dir/Makefile deleted file mode 100644 index abdba4eb8614..000000000000 --- a/tests/run-make/inaccessible-temp-dir/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# only-linux -# ignore-arm - linker error on `armhf-gnu` - -include ../tools.mk - -# Issue #66530: We would ICE if someone compiled with `-o /dev/null`, -# because we would try to generate auxiliary files in `/dev/` (which -# at least the OS X file system rejects). -# -# An attempt to `-Ztemps-dir` into a directory we cannot write into should -# indeed be an error; but not an ICE. -# -# However, some folks run tests as root, which can write `/dev/` and end -# up clobbering `/dev/null`. Instead we'll use an inaccessible path, which -# also used to ICE, but even root can't magically write there. -# -# Note that `-Ztemps-dir` uses `create_dir_all` so it is not sufficient to -# use a directory with non-existing parent like `/does-not-exist/output`. - -all: - # Create an inaccessible directory - mkdir $(TMPDIR)/inaccessible - chmod 000 $(TMPDIR)/inaccessible - - # Run rustc with `-Ztemps-dir` set to a directory - # *inside* the inaccessible one, so that it can't create it - $(RUSTC) program.rs -Ztemps-dir=$(TMPDIR)/inaccessible/tmp 2>&1 \ - | $(CGREP) 'failed to find or create the directory specified by `--temps-dir`' - - # Make the inaccessible directory accessible, - # so that compiletest can delete the temp dir - chmod +rw $(TMPDIR)/inaccessible diff --git a/tests/run-make/inaccessible-temp-dir/rmake.rs b/tests/run-make/inaccessible-temp-dir/rmake.rs new file mode 100644 index 000000000000..be24e47b6dec --- /dev/null +++ b/tests/run-make/inaccessible-temp-dir/rmake.rs @@ -0,0 +1,38 @@ +// Issue #66530: We would ICE if someone compiled with `-o /dev/null`, +// because we would try to generate auxiliary files in `/dev/` (which +// at least the OS X file system rejects). +// +// An attempt to `-Ztemps-dir` into a directory we cannot write into should +// indeed be an error; but not an ICE. +// +// However, some folks run tests as root, which can write `/dev/` and end +// up clobbering `/dev/null`. Instead we'll use an inaccessible path, which +// also used to ICE, but even root can't magically write there. +// +// Note that `-Ztemps-dir` uses `create_dir_all` so it is not sufficient to +// use a directory with non-existing parent like `/does-not-exist/output`. +// See https://github.com/rust-lang/rust/issues/66530 + +//@ ignore-arm +// Reason: linker error on `armhf-gnu` +//@ ignore-windows +// Reason: `set_readonly` has no effect on directories +// and does not prevent modification. + +use run_make_support::{fs_wrapper, rustc, test_while_readonly}; + +fn main() { + // Create an inaccessible directory. + fs_wrapper::create_dir("inaccessible"); + test_while_readonly("inaccessible", || { + // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one, + // so that it can't create `tmp`. + rustc() + .input("program.rs") + .arg("-Ztemps-dir=inaccessible/tmp") + .run_fail() + .assert_stderr_contains( + "failed to find or create the directory specified by `--temps-dir`", + ); + }); +} diff --git a/tests/run-make/issue-10971-temps-dir/Makefile b/tests/run-make/issue-10971-temps-dir/Makefile deleted file mode 100644 index 6e1649a58d23..000000000000 --- a/tests/run-make/issue-10971-temps-dir/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -include ../tools.mk - -# Regression test for issue #10971 -# Running two invocations in parallel would overwrite each other's temp files. - -all: - touch $(TMPDIR)/lib.rs - - $(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \ - $(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs diff --git a/tests/run-make/issue-26092/Makefile b/tests/run-make/issue-26092/Makefile deleted file mode 100644 index 96822e7690be..000000000000 --- a/tests/run-make/issue-26092/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include ../tools.mk - -# This test ensures that rustc does not panic with `-o ""` option. - -all: - $(RUSTC) -o "" blank.rs 2>&1 | $(CGREP) -i 'panic' && exit 1 || exit 0 diff --git a/tests/run-make/issue-47551/Makefile b/tests/run-make/issue-47551/Makefile index 5a6ac725701b..3fe0a6e74e02 100644 --- a/tests/run-make/issue-47551/Makefile +++ b/tests/run-make/issue-47551/Makefile @@ -4,6 +4,7 @@ include ../tools.mk all: - $(RUSTC) eh_frame-terminator.rs + # --target $(TARGET) ensures the right gcc flags are used for cross compilation + $(RUSTC) --target $(TARGET) eh_frame-terminator.rs $(call RUN,eh_frame-terminator) | $(CGREP) '1122334455667788' objdump --dwarf=frames $(TMPDIR)/eh_frame-terminator | $(CGREP) 'ZERO terminator' diff --git a/tests/run-make/link-arg/Makefile b/tests/run-make/link-arg/Makefile deleted file mode 100644 index 103527c3e14d..000000000000 --- a/tests/run-make/link-arg/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk -RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" --print link-args - -all: - $(RUSTC) $(RUSTC_FLAGS) empty.rs | $(CGREP) lfoo lbar diff --git a/tests/run-make/link-arg/rmake.rs b/tests/run-make/link-arg/rmake.rs new file mode 100644 index 000000000000..a6d68800792f --- /dev/null +++ b/tests/run-make/link-arg/rmake.rs @@ -0,0 +1,20 @@ +// In 2016, the rustc flag "-C link-arg" was introduced - it can be repeatedly used +// to add single arguments to the linker. This test passes 2 arguments to the linker using it, +// then checks that the compiler's output contains the arguments passed to it. +// This ensures that the compiler successfully parses this flag. +// See https://github.com/rust-lang/rust/pull/36574 + +use run_make_support::rustc; + +fn main() { + // We are only checking for the output of --print=link-args, + // rustc failing or succeeding does not matter. + let out = rustc() + .input("empty.rs") + .link_arg("-lfoo") + .link_arg("-lbar") + .print("link-args") + .run_unchecked(); + out.assert_stdout_contains("lfoo"); + out.assert_stdout_contains("lbar"); +} diff --git a/tests/run-make/link-dedup/Makefile b/tests/run-make/link-dedup/Makefile deleted file mode 100644 index eff18ab48ab4..000000000000 --- a/tests/run-make/link-dedup/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-msvc - -include ../tools.mk - -all: - $(RUSTC) depa.rs - $(RUSTC) depb.rs - $(RUSTC) depc.rs - $(RUSTC) empty.rs --cfg bar 2>&1 | $(CGREP) '"-ltesta" "-ltestb" "-ltesta"' - $(RUSTC) empty.rs 2>&1 | $(CGREP) '"-ltesta"' - $(RUSTC) empty.rs 2>&1 | $(CGREP) -v '"-ltestb"' - $(RUSTC) empty.rs 2>&1 | $(CGREP) -v '"-ltesta" "-ltesta" "-ltesta"' diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs new file mode 100644 index 000000000000..9bff3a4b44c7 --- /dev/null +++ b/tests/run-make/link-dedup/rmake.rs @@ -0,0 +1,24 @@ +// When native libraries are passed to the linker, there used to be an annoyance +// where multiple instances of the same library in a row would cause duplication in +// outputs. This has been fixed, and this test checks that it stays fixed. +// With the --cfg flag, -ltestb gets added to the output, breaking up the chain of -ltesta. +// Without the --cfg flag, there should be a single -ltesta, no more, no less. +// See https://github.com/rust-lang/rust/pull/84794 + +//@ ignore-msvc + +use run_make_support::rustc; + +fn main() { + rustc().input("depa.rs").run(); + rustc().input("depb.rs").run(); + rustc().input("depc.rs").run(); + let output = rustc().input("empty.rs").cfg("bar").run_fail(); + output.assert_stderr_contains(r#""-ltesta" "-ltestb" "-ltesta""#); + let output = rustc().input("empty.rs").run_fail(); + output.assert_stderr_contains(r#""-ltesta""#); + let output = rustc().input("empty.rs").run_fail(); + output.assert_stderr_not_contains(r#""-ltestb""#); + let output = rustc().input("empty.rs").run_fail(); + output.assert_stderr_not_contains(r#""-ltesta" "-ltesta" "-ltesta""#); +} diff --git a/tests/run-make/output-with-hyphens/Makefile b/tests/run-make/output-with-hyphens/Makefile deleted file mode 100644 index 846c9a66a89a..000000000000 --- a/tests/run-make/output-with-hyphens/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo-bar.rs --crate-type bin - [ -f $(TMPDIR)/$(call BIN,foo-bar) ] - $(RUSTC) foo-bar.rs --crate-type lib - [ -f $(TMPDIR)/libfoo_bar.rlib ] diff --git a/tests/run-make/output-with-hyphens/rmake.rs b/tests/run-make/output-with-hyphens/rmake.rs new file mode 100644 index 000000000000..79deb772bc5d --- /dev/null +++ b/tests/run-make/output-with-hyphens/rmake.rs @@ -0,0 +1,17 @@ +// Rust files with hyphens in their filename should +// not result in compiled libraries keeping that hyphen - +// it should become an underscore. Only bin executables +// should keep the hyphen. This test ensures that this rule +// remains enforced. +// See https://github.com/rust-lang/rust/pull/23786 + +//@ ignore-cross-compile + +use run_make_support::{bin_name, path, rust_lib_name, rustc}; + +fn main() { + rustc().input("foo-bar.rs").crate_type("bin").run(); + assert!(path(bin_name("foo-bar")).exists()); + rustc().input("foo-bar.rs").crate_type("lib").run(); + assert!(path(rust_lib_name("foo_bar")).exists()); +} diff --git a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs new file mode 100644 index 000000000000..3f032cf3762a --- /dev/null +++ b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs @@ -0,0 +1,25 @@ +// When two instances of rustc are invoked in parallel, they +// can conflict on their temporary files and overwrite each others', +// leading to unsuccessful compilation. The -Z temps-dir flag adds +// separate designated directories for each rustc invocation, preventing +// conflicts. This test uses this flag and checks for successful compilation. +// See https://github.com/rust-lang/rust/pull/83846 + +use run_make_support::{fs_wrapper, rustc}; +use std::sync::{Arc, Barrier}; +use std::thread; + +fn main() { + fs_wrapper::create_file("lib.rs"); + let barrier = Arc::new(Barrier::new(2)); + let handle = { + let barrier = Arc::clone(&barrier); + thread::spawn(move || { + barrier.wait(); + rustc().crate_type("lib").arg("-Ztemps-dir=temp1").input("lib.rs").run(); + }) + }; + barrier.wait(); + rustc().crate_type("staticlib").arg("-Ztemps-dir=temp2").input("lib.rs").run(); + handle.join().expect("lib thread panicked"); +} diff --git a/tests/ui/associated-consts/double-elided.rs b/tests/ui/associated-consts/double-elided.rs index fd0317781bb1..6831b599374a 100644 --- a/tests/ui/associated-consts/double-elided.rs +++ b/tests/ui/associated-consts/double-elided.rs @@ -1,12 +1,10 @@ +//@ check-pass + struct S; impl S { const C: &&str = &""; - //~^ WARN `&` without an explicit lifetime name cannot be used here - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| WARN `&` without an explicit lifetime name cannot be used here - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| ERROR in type `&&str`, reference has a longer lifetime than the data it references + // Now resolves to `&'static &'static str`. } fn main() {} diff --git a/tests/ui/associated-consts/double-elided.stderr b/tests/ui/associated-consts/double-elided.stderr deleted file mode 100644 index 67834788ccd4..000000000000 --- a/tests/ui/associated-consts/double-elided.stderr +++ /dev/null @@ -1,47 +0,0 @@ -warning: `&` without an explicit lifetime name cannot be used here - --> $DIR/double-elided.rs:4:14 - | -LL | const C: &&str = &""; - | ^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 - = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default -help: use the `'static` lifetime - | -LL | const C: &'static &str = &""; - | +++++++ - -warning: `&` without an explicit lifetime name cannot be used here - --> $DIR/double-elided.rs:4:15 - | -LL | const C: &&str = &""; - | ^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 -help: use the `'static` lifetime - | -LL | const C: &&'static str = &""; - | +++++++ - -error[E0491]: in type `&&str`, reference has a longer lifetime than the data it references - --> $DIR/double-elided.rs:4:5 - | -LL | const C: &&str = &""; - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: the pointer is valid for the anonymous lifetime as defined here - --> $DIR/double-elided.rs:4:14 - | -LL | const C: &&str = &""; - | ^ -note: but the referenced data is only valid for the anonymous lifetime as defined here - --> $DIR/double-elided.rs:4:14 - | -LL | const C: &&str = &""; - | ^ - -error: aborting due to 1 previous error; 2 warnings emitted - -For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs index 1e0b77b0d3bd..40896c32e111 100644 --- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs +++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs @@ -5,8 +5,6 @@ trait Trait { impl Trait for () { const ASSOC: &dyn Fn(_) = 1i32; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants - //~| WARN `&` without an explicit lifetime name cannot be used here - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } fn main() {} diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr index e946491a0848..6b8ba9af7a07 100644 --- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr +++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr @@ -1,23 +1,9 @@ -warning: `&` without an explicit lifetime name cannot be used here - --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18 - | -LL | const ASSOC: &dyn Fn(_) = 1i32; - | ^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 - = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default -help: use the `'static` lifetime - | -LL | const ASSOC: &'static dyn Fn(_) = 1i32; - | +++++++ - error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26 | LL | const ASSOC: &dyn Fn(_) = 1i32; | ^ not allowed in type signatures -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs new file mode 100644 index 000000000000..e2fc2961a448 --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs @@ -0,0 +1,10 @@ +struct Fail; +//~^ ERROR: type parameter `T` is never used + +impl Fail { + const C: () = (); +} + +fn main() { + Fail::<()>::C +} diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr new file mode 100644 index 000000000000..f0a6ccf243a9 --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr @@ -0,0 +1,12 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg.rs:1:13 + | +LL | struct Fail; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs new file mode 100644 index 000000000000..cb53d902ba18 --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs @@ -0,0 +1,17 @@ +trait Proj { + type Assoc; +} +impl Proj for T { + type Assoc = T; +} + +struct Fail, U>(T); + +impl Fail { + const C: () = (); +} + +fn main() { + Fail::::C + //~^ ERROR: type mismatch +} diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr new file mode 100644 index 000000000000..0d63b7f5b293 --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `::Assoc == u32` + --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:5 + | +LL | Fail::::C + | ^^^^^^^^^^^^^^^^ type mismatch resolving `::Assoc == u32` + | +note: expected this to be `u32` + --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:5:18 + | +LL | type Assoc = T; + | ^ +note: required by a bound in `Fail` + --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:8:21 + | +LL | struct Fail, U>(T); + | ^^^^^^^^^ required by this bound in `Fail` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.rs b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.rs new file mode 100644 index 000000000000..637c47f29396 --- /dev/null +++ b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.rs @@ -0,0 +1,14 @@ +// This test was triggering a `span_bug` crash, which was then fixed by +// downgrading it to a `span_delayed_bug`. + +pub struct MyStruct<'field> { + field: &'field [u32], +} + +impl MyStruct<'_> { + pub fn f(field: &[u32]) -> Self { //~ ERROR type arguments are not allowed on self type + Self { field } //~ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr new file mode 100644 index 000000000000..0ae301b2090a --- /dev/null +++ b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr @@ -0,0 +1,34 @@ +error[E0109]: type arguments are not allowed on self type + --> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:9:37 + | +LL | pub fn f(field: &[u32]) -> Self { + | ---- ^^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `MyStruct<'_>` + --> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:4:12 + | +LL | pub struct MyStruct<'field> { + | ^^^^^^^^ `Self` corresponds to this type +... +LL | impl MyStruct<'_> { + | ----------------- `Self` is on type `MyStruct` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `MyStruct` instead if you want to specify its type parameters + | +LL | pub fn f(field: &[u32]) -> MyStruct { + | ~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:10:9 + | +LL | pub fn f(field: &[u32]) -> Self { + | - --------- return type is MyStruct<'2> + | | + | let's call the lifetime of this reference `'1` +LL | Self { field } + | ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs b/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs new file mode 100644 index 000000000000..ce575697cf68 --- /dev/null +++ b/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs @@ -0,0 +1,29 @@ +// Regression test for #125325 + +// Tests that we suggest changing an `impl Fn` param +// to `impl FnMut` when the provided closure arg +// is trying to mutate the closure env. +// Ensures that it works that way for both +// functions and methods + +struct S; + +impl S { + fn assoc_func(&self, _f: impl Fn()) -> usize { + 0 + } +} + +fn func(_f: impl Fn()) -> usize { + 0 +} + +fn test_func(s: &S) -> usize { + let mut x = (); + s.assoc_func(|| x = ()); + //~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure + func(|| x = ()) + //~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure +} + +fn main() {} diff --git a/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr new file mode 100644 index 000000000000..e0cce8c4b314 --- /dev/null +++ b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr @@ -0,0 +1,28 @@ +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/wrong-closure-arg-suggestion-125325.rs:23:21 + | +LL | fn assoc_func(&self, _f: impl Fn()) -> usize { + | --------- change this to accept `FnMut` instead of `Fn` +... +LL | s.assoc_func(|| x = ()); + | --------------^^^^^^- + | | | | + | | | cannot assign + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/wrong-closure-arg-suggestion-125325.rs:25:13 + | +LL | fn func(_f: impl Fn()) -> usize { + | --------- change this to accept `FnMut` instead of `Fn` +... +LL | func(|| x = ()) + | ---- -- ^^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr deleted file mode 100644 index b976f70acf76..000000000000 --- a/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never-windows.rs:18:53 - | -LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` - | - = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` - -error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never-windows.rs:23:49 - | -LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` - | - = note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs b/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs deleted file mode 100644 index b317841ab6e7..000000000000 --- a/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs +++ /dev/null @@ -1,58 +0,0 @@ -//@ revisions: nofallback fallback -//@ only-windows - the number of `Error` impls is platform-dependent -//@[fallback] check-pass -//@[nofallback] check-fail - -#![feature(never_type)] -#![cfg_attr(fallback, feature(never_type_fallback))] -#![allow(unreachable_code)] - -use std::error::Error; -use std::mem; - -fn raw_ptr_box(t: T) -> *mut T { - panic!() -} - -fn foo(x: !) -> Box { - /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) - //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied -} - -fn foo_raw_ptr(x: !) -> *mut dyn Error { - /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) - //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied -} - -fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { - /* an unsize coercion won't compile here, and it is indeed not used - because there is nothing requiring the _ to be Sized */ - d as *mut _ -} - -trait Xyz {} -struct S; -struct T; -impl Xyz for S {} -impl Xyz for T {} - -fn foo_no_never() { - let mut x /* : Option */ = None; - let mut first_iter = false; - loop { - if !first_iter { - let y: Box - = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); - } - - x = Some(S); - first_iter = true; - } - - let mut y : Option = None; - // assert types are equal - mem::swap(&mut x, &mut y); -} - -fn main() { -} diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr new file mode 100644 index 000000000000..ef5633f71348 --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:18:5 + | +LL | Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index 0d98fa93e5a4..7222af43b013 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -1,16 +1,16 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:18:53 + --> $DIR/coerce-issue-49593-box-never.rs:18:5 | -LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` +LL | Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:23:49 + --> $DIR/coerce-issue-49593-box-never.rs:24:5 | -LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` +LL | raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | = note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)` diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.rs b/tests/ui/coercion/coerce-issue-49593-box-never.rs index 19a2c036fbcb..53071be47dcb 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.rs +++ b/tests/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,7 +1,5 @@ //@ revisions: nofallback fallback -//@ ignore-windows - the number of `Error` impls is platform-dependent -//@[fallback] check-pass -//@[nofallback] check-fail +//@check-fail #![feature(never_type)] #![cfg_attr(fallback, feature(never_type_fallback))] @@ -15,18 +13,21 @@ fn raw_ptr_box(t: T) -> *mut T { } fn foo(x: !) -> Box { - /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) - //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied + // Subtyping during method resolution will generate new inference vars and + // subtype them. Thus fallback will not fall back to `!`, but `()` instead. + Box::<_ /* ! */>::new(x) + //~^ ERROR trait bound `(): std::error::Error` is not satisfied } fn foo_raw_ptr(x: !) -> *mut dyn Error { - /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + /* *mut $0 is coerced to *mut Error here */ + raw_ptr_box::<_ /* ! */>(x) //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied } fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { /* an unsize coercion won't compile here, and it is indeed not used - because there is nothing requiring the _ to be Sized */ + because there is nothing requiring the _ to be Sized */ d as *mut _ } @@ -49,10 +50,9 @@ fn foo_no_never() { first_iter = true; } - let mut y : Option = None; + let mut y: Option = None; // assert types are equal mem::swap(&mut x, &mut y); } -fn main() { -} +fn main() {} diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index 5ee42c19dd3d..563406ad5eaa 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -15,7 +15,7 @@ note: required by a bound in `Mask::::splat` --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL help: consider giving `y` an explicit type, where the type for type parameter `T` is specified | -LL | let y: Mask<_, N> = Mask::<_, _>::splat(false); +LL | let y: Mask = Mask::<_, _>::splat(false); | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr index a1eeaff4ba87..3e847298c356 100644 --- a/tests/ui/consts/assoc-const-elided-lifetime.stderr +++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr @@ -6,6 +6,11 @@ LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/assoc-const-elided-lifetime.rs:9:6 + | +LL | impl<'a> Foo<'a> { + | ^^ note: the lint level is defined here --> $DIR/assoc-const-elided-lifetime.rs:1:9 | @@ -24,6 +29,13 @@ LL | const BAR: &() = &(); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/assoc-const-elided-lifetime.rs:9:6 + | +LL | impl<'a> Foo<'a> { + | ^^ +LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; + | ^^ help: use the `'static` lifetime | LL | const BAR: &'static () = &(); diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs new file mode 100644 index 000000000000..95d59f9b894e --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs @@ -0,0 +1,22 @@ +#![deny(elided_lifetimes_in_associated_constant)] + +struct Foo<'a>(&'a ()); + +impl Foo<'_> { + const STATIC: &str = ""; + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out +} + +trait Bar { + const STATIC: &str; +} + +impl Bar for Foo<'_> { + const STATIC: &str = ""; + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out + //~| ERROR const not compatible with trait +} + +fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr new file mode 100644 index 000000000000..d4fc17175389 --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -0,0 +1,59 @@ +error: `&` without an explicit lifetime name cannot be used here + --> $DIR/elided-lifetime.rs:6:19 + | +LL | const STATIC: &str = ""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/elided-lifetime.rs:5:10 + | +LL | impl Foo<'_> { + | ^^ +note: the lint level is defined here + --> $DIR/elided-lifetime.rs:1:9 + | +LL | #![deny(elided_lifetimes_in_associated_constant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the `'static` lifetime + | +LL | const STATIC: &'static str = ""; + | +++++++ + +error: `&` without an explicit lifetime name cannot be used here + --> $DIR/elided-lifetime.rs:16:19 + | +LL | const STATIC: &str = ""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/elided-lifetime.rs:15:18 + | +LL | impl Bar for Foo<'_> { + | ^^ +help: use the `'static` lifetime + | +LL | const STATIC: &'static str = ""; + | +++++++ + +error[E0308]: const not compatible with trait + --> $DIR/elided-lifetime.rs:16:5 + | +LL | const STATIC: &str = ""; + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'static _` + found reference `&_` +note: the anonymous lifetime as defined here... + --> $DIR/elided-lifetime.rs:15:18 + | +LL | impl Bar for Foo<'_> { + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.rs b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs new file mode 100644 index 000000000000..721920bd810c --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs @@ -0,0 +1,19 @@ +#![deny(elided_lifetimes_in_associated_constant)] +#![feature(generic_const_items)] +//~^ WARN the feature `generic_const_items` is incomplete + +struct A; +impl A { + const GAC_TYPE: &str = ""; + const GAC_LIFETIME<'a>: &str = ""; + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out +} + +trait Trait { + const GAC_TYPE: &str = ""; + const GAC_LIFETIME<'a>: &str = ""; + //~^ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr new file mode 100644 index 000000000000..2ecab3442a96 --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr @@ -0,0 +1,46 @@ +error[E0106]: missing lifetime specifier + --> $DIR/generic-associated-const.rs:15:29 + | +LL | const GAC_LIFETIME<'a>: &str = ""; + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | const GAC_LIFETIME<'a>: &'a str = ""; + | ++ + +warning: the feature `generic_const_items` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/generic-associated-const.rs:2:12 + | +LL | #![feature(generic_const_items)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: `&` without an explicit lifetime name cannot be used here + --> $DIR/generic-associated-const.rs:8:29 + | +LL | const GAC_LIFETIME<'a>: &str = ""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/generic-associated-const.rs:8:24 + | +LL | const GAC_LIFETIME<'a>: &str = ""; + | ^^ +note: the lint level is defined here + --> $DIR/generic-associated-const.rs:1:9 + | +LL | #![deny(elided_lifetimes_in_associated_constant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the `'static` lifetime + | +LL | const GAC_LIFETIME<'a>: &'static str = ""; + | +++++++ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/consts/static-default-lifetime/inner-item.rs b/tests/ui/consts/static-default-lifetime/inner-item.rs new file mode 100644 index 000000000000..061b240a40d8 --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/inner-item.rs @@ -0,0 +1,21 @@ +//@ check-pass + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn hello(self) { + const INNER: &str = ""; + } +} + +impl Foo<'_> { + fn implicit(self) { + const INNER: &str = ""; + } + + fn fn_lifetime(&self) { + const INNER: &str = ""; + } +} + +fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs new file mode 100644 index 000000000000..025fda4df581 --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs @@ -0,0 +1,20 @@ +#![deny(elided_lifetimes_in_associated_constant)] + +trait Bar<'a> { + const STATIC: &'a str; +} + +struct A; +impl Bar<'_> for A { + const STATIC: &str = ""; + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out + //~| ERROR const not compatible with trait +} + +struct B; +impl Bar<'static> for B { + const STATIC: &str = ""; +} + +fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr new file mode 100644 index 000000000000..8e4c27875ab3 --- /dev/null +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -0,0 +1,45 @@ +error: `&` without an explicit lifetime name cannot be used here + --> $DIR/static-trait-impl.rs:9:19 + | +LL | const STATIC: &str = ""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +note: cannot automatically infer `'static` because of other lifetimes in scope + --> $DIR/static-trait-impl.rs:8:10 + | +LL | impl Bar<'_> for A { + | ^^ +note: the lint level is defined here + --> $DIR/static-trait-impl.rs:1:9 + | +LL | #![deny(elided_lifetimes_in_associated_constant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the `'static` lifetime + | +LL | const STATIC: &'static str = ""; + | +++++++ + +error[E0308]: const not compatible with trait + --> $DIR/static-trait-impl.rs:9:5 + | +LL | const STATIC: &str = ""; + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&_` + found reference `&_` +note: the anonymous lifetime as defined here... + --> $DIR/static-trait-impl.rs:8:10 + | +LL | impl Bar<'_> for A { + | ^^ +note: ...does not necessarily outlive the anonymous lifetime as defined here + --> $DIR/static-trait-impl.rs:8:10 + | +LL | impl Bar<'_> for A { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-3.rs b/tests/ui/imports/shadow-glob-module-resolution-3.rs new file mode 100644 index 000000000000..f5a43373261b --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-3.rs @@ -0,0 +1,19 @@ +// https://github.com/rust-lang/rust/issues/126389 + +mod a { + pub mod b { + pub mod c {} + } +} + +use a::*; + +use b::c; +//~^ ERROR: unresolved import `b::c` +//~| ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import +use c as b; + +fn c() {} + +fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-3.stderr b/tests/ui/imports/shadow-glob-module-resolution-3.stderr new file mode 100644 index 000000000000..ab853c715828 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-3.stderr @@ -0,0 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-3.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-3.rs:11:5 + | +LL | use b::c; + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `b::c` + --> $DIR/shadow-glob-module-resolution-3.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.rs b/tests/ui/imports/shadow-glob-module-resolution-4.rs new file mode 100644 index 000000000000..581cdc185d3f --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-4.rs @@ -0,0 +1,20 @@ +// https://github.com/rust-lang/rust/issues/126376 + +mod a { + pub mod b { + pub trait C {} + } +} + +use a::*; + +use e as b; + +use b::C as e; +//~^ ERROR: unresolved import `b::C` +//~| ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import + +fn e() {} + +fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.stderr b/tests/ui/imports/shadow-glob-module-resolution-4.stderr new file mode 100644 index 000000000000..063beb612b13 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-4.stderr @@ -0,0 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-4.rs:13:5 + | +LL | use b::C as e; + | ^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-4.rs:13:5 + | +LL | use b::C as e; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `b::C` + --> $DIR/shadow-glob-module-resolution-4.rs:13:5 + | +LL | use b::C as e; + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.stderr b/tests/ui/inference/need_type_info/type-alias-indirect.stderr index 535c0044aec0..5c5b4c149c17 100644 --- a/tests/ui/inference/need_type_info/type-alias-indirect.stderr +++ b/tests/ui/inference/need_type_info/type-alias-indirect.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/type-alias-indirect.rs:14:5 | LL | IndirectAlias::new(); - | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` error: aborting due to 1 previous error diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr index 2c39a3f56466..fd9bcf2fe3f3 100644 --- a/tests/ui/inference/need_type_info/type-alias.stderr +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -2,19 +2,19 @@ error[E0282]: type annotations needed --> $DIR/type-alias.rs:12:5 | LL | DirectAlias::new() - | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectAlias` error[E0282]: type annotations needed --> $DIR/type-alias.rs:18:5 | LL | IndirectAlias::new(); - | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` error[E0282]: type annotations needed --> $DIR/type-alias.rs:32:5 | LL | DirectButWithDefaultAlias::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectButWithDefaultAlias` error: aborting due to 3 previous errors diff --git a/tests/crashes/122736.rs b/tests/ui/privacy/no-ice-on-inference-failure.rs similarity index 80% rename from tests/crashes/122736.rs rename to tests/ui/privacy/no-ice-on-inference-failure.rs index 83b60444c2f4..e63b7bff9bc4 100644 --- a/tests/crashes/122736.rs +++ b/tests/ui/privacy/no-ice-on-inference-failure.rs @@ -1,9 +1,9 @@ -//@ known-bug: #122736 fn main_ref() { let array = [(); { let mut x = &0; let mut n = 0; while n < 5 { + //~^ ERROR constant evaluation is taking a long time x = &0; } 0 diff --git a/tests/ui/privacy/no-ice-on-inference-failure.stderr b/tests/ui/privacy/no-ice-on-inference-failure.stderr new file mode 100644 index 000000000000..67476e6e2189 --- /dev/null +++ b/tests/ui/privacy/no-ice-on-inference-failure.stderr @@ -0,0 +1,27 @@ +error: constant evaluation is taking a long time + --> $DIR/no-ice-on-inference-failure.rs:5:9 + | +LL | / while n < 5 { +LL | | +LL | | x = &0; +LL | | } + | |_________^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/no-ice-on-inference-failure.rs:2:22 + | +LL | let array = [(); { + | ______________________^ +LL | | let mut x = &0; +LL | | let mut n = 0; +LL | | while n < 5 { +... | +LL | | 0 +LL | | }]; + | |_____^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/statics/const_generics.rs b/tests/ui/statics/const_generics.rs new file mode 100644 index 000000000000..70d9b933a765 --- /dev/null +++ b/tests/ui/statics/const_generics.rs @@ -0,0 +1,26 @@ +//! Check that we lose the information that `BAR` points to `FOO` +//! when going through a const generic. +//! This is not an intentional guarantee, it just describes the status quo. + +//@ run-pass +// With optimizations, LLVM will deduplicate the constant `X` whose +// value is `&42` to just be a reference to the static. This is correct, +// but obscures the issue we're trying to show. +//@ revisions: opt noopt +//@[noopt] compile-flags: -Copt-level=0 +//@[opt] compile-flags: -O + +#![feature(const_refs_to_static)] +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +static FOO: usize = 42; +const BAR: &usize = &FOO; +fn foo() { + // Without optimizations, `X` ends up pointing to a copy of `FOO` instead of `FOO` itself. + assert_eq!(cfg!(opt), std::ptr::eq(X, &FOO)); +} + +fn main() { + foo::(); +} diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr index 24e2e0a0f7a2..71ac55bf0448 100644 --- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr +++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr @@ -1,57 +1,25 @@ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14 - | -LL | const A: &str = ""; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL ~ trait ZstAssert<'a>: Sized { -LL ~ const A: &'a str = ""; - | - -error[E0106]: missing lifetime specifier +error[E0726]: implicit elided lifetime not allowed here --> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14 | LL | const B: S = S { s: &() }; - | ^ expected named lifetime parameter + | ^ expected lifetime parameter | -help: consider introducing a named lifetime parameter - | -LL ~ trait ZstAssert<'a>: Sized { -LL | const A: &str = ""; -LL ~ const B: S<'a> = S { s: &() }; +help: indicate the anonymous lifetime | +LL | const B: S<'_> = S { s: &() }; + | ++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15 - | -LL | const C: &'_ str = ""; - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL ~ trait ZstAssert<'a>: Sized { -LL | const A: &str = ""; -LL | const B: S = S { s: &() }; -LL ~ const C: &'a str = ""; - | - -error[E0106]: missing lifetime specifiers +error[E0726]: implicit elided lifetime not allowed here --> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14 | LL | const D: T = T { a: &(), b: &() }; - | ^ expected 2 lifetime parameters + | ^ expected lifetime parameters | -help: consider introducing a named lifetime parameter - | -LL ~ trait ZstAssert<'a>: Sized { -LL | const A: &str = ""; -LL | const B: S = S { s: &() }; -LL | const C: &'_ str = ""; -LL ~ const D: T<'a, 'a> = T { a: &(), b: &() }; +help: indicate the anonymous lifetimes | +LL | const D: T<'_, '_> = T { a: &(), b: &() }; + | ++++++++ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr index a97ffe7da79e..71ac55bf0448 100644 --- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr +++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr @@ -1,47 +1,25 @@ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14 - | -LL | const A: &str = ""; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | const A<'a>: &'a str = ""; - | ++++ ++ - -error[E0106]: missing lifetime specifier +error[E0726]: implicit elided lifetime not allowed here --> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14 | LL | const B: S = S { s: &() }; - | ^ expected named lifetime parameter + | ^ expected lifetime parameter | -help: consider introducing a named lifetime parameter +help: indicate the anonymous lifetime | -LL | const B<'a>: S<'a> = S { s: &() }; - | ++++ ++++ +LL | const B: S<'_> = S { s: &() }; + | ++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15 - | -LL | const C: &'_ str = ""; - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | const C<'a>: &'a str = ""; - | ++++ ~~ - -error[E0106]: missing lifetime specifiers +error[E0726]: implicit elided lifetime not allowed here --> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14 | LL | const D: T = T { a: &(), b: &() }; - | ^ expected 2 lifetime parameters + | ^ expected lifetime parameters | -help: consider introducing a named lifetime parameter +help: indicate the anonymous lifetimes | -LL | const D<'a>: T<'a, 'a> = T { a: &(), b: &() }; - | ++++ ++++++++ +LL | const D: T<'_, '_> = T { a: &(), b: &() }; + | ++++++++ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs index f36a6567e423..a60f0b94587f 100644 --- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs +++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs @@ -3,10 +3,10 @@ #![cfg_attr(generic_const_items, feature(generic_const_items), allow(incomplete_features))] trait ZstAssert: Sized { - const A: &str = ""; //~ ERROR missing lifetime specifier - const B: S = S { s: &() }; //~ ERROR missing lifetime specifier - const C: &'_ str = ""; //~ ERROR missing lifetime specifier - const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier + const A: &str = ""; + const B: S = S { s: &() }; //~ ERROR implicit elided lifetime not allowed here + const C: &'_ str = ""; + const D: T = T { a: &(), b: &() }; //~ ERROR implicit elided lifetime not allowed here } struct S<'a> { diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs index 66e1e77c905e..924bfd82eb83 100644 --- a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -17,6 +17,7 @@ fn main() { let fp = BufWriter::new(fp); //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied writeln!(fp, "hello world").unwrap(); //~ ERROR the method } diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr index 09a9b1d3b348..b2f9150142fe 100644 --- a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -10,6 +10,16 @@ LL | let fp = BufWriter::new(fp); note: required by a bound in `BufWriter::::new` --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` +note: required by a bound in `BufWriter` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied --> $DIR/mut-borrow-needed-by-trait.rs:17:14 | @@ -21,13 +31,13 @@ note: required by a bound in `BufWriter` --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:22:14 | LL | writeln!(fp, "hello world").unwrap(); | ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds | note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:22:14 | LL | writeln!(fp, "hello world").unwrap(); | ^^ @@ -35,7 +45,7 @@ LL | writeln!(fp, "hello world").unwrap(); `&dyn std::io::Write: std::io::Write` which is required by `BufWriter<&dyn std::io::Write>: std::io::Write` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0599. For more information about an error, try `rustc --explain E0277`.