From 59a3a5dba314d4b693d141a56fde2e6a879d0af0 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 07:55:23 -0800 Subject: [PATCH 01/16] Clarify atomic bit validity The previous definition used the phrase "representation", which is ambiguous given the current state of memory model nomenclature in Rust. The new wording clarifies that size and bit validity are guaranteed to match the corresponding native integer type. --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 45193c11e1d6b..303f1bf8f65e4 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2121,7 +2121,7 @@ macro_rules! atomic_int { $int_type:ident $atomic_type:ident) => { /// An integer type which can be safely shared between threads. /// - /// This type has the same in-memory representation as the underlying + /// This type has the same in-memory size and bit validity as the underlying /// integer type, [` #[doc = $s_int_type] /// `]. From db34b082c0895e80bc9eda17a4c859c51e6509bd Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 07:57:35 -0800 Subject: [PATCH 02/16] Clarify bit validity for AtomicBool --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 303f1bf8f65e4..5947f6569a7fa 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -243,7 +243,7 @@ const EMULATE_ATOMIC_BOOL: bool = /// A boolean type which can be safely shared between threads. /// -/// This type has the same in-memory representation as a [`bool`]. +/// This type has the same memory layout and bit validity as a [`bool`]. /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of `u8`. From 00d21c91f0cafc97dabe261f934af7ea0df089b4 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 08:04:41 -0800 Subject: [PATCH 03/16] Document AtomicPtr bit validity --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5947f6569a7fa..4eaacdfe7945b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -272,7 +272,7 @@ unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// -/// This type has the same in-memory representation as a `*mut T`. +/// This type has the same memory layout and bit validity as a `*mut T`. /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of pointers. Its size depends on the target pointer's size. From fba87f6892a052fdaed45993a1ec03d6c51ab87d Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 08:06:41 -0800 Subject: [PATCH 04/16] Use "size and alignment" rather than layout --- library/core/src/sync/atomic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 4eaacdfe7945b..0a0daa49926a2 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -243,7 +243,7 @@ const EMULATE_ATOMIC_BOOL: bool = /// A boolean type which can be safely shared between threads. /// -/// This type has the same memory layout and bit validity as a [`bool`]. +/// This type has the same size, alignment, and bit validity as a [`bool`]. /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of `u8`. @@ -272,7 +272,7 @@ unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// -/// This type has the same memory layout and bit validity as a `*mut T`. +/// This type has the same size, alignment, and bit validity as a `*mut T`. /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of pointers. Its size depends on the target pointer's size. From c50804cfdd5deac77a8eff6e1b2303b6453e786f Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 08:08:52 -0800 Subject: [PATCH 05/16] Update library/core/src/sync/atomic.rs Co-authored-by: Taiki Endo --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 0a0daa49926a2..aac0acbadbfc9 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2121,7 +2121,7 @@ macro_rules! atomic_int { $int_type:ident $atomic_type:ident) => { /// An integer type which can be safely shared between threads. /// - /// This type has the same in-memory size and bit validity as the underlying + /// This type has the same size and bit validity as the underlying /// integer type, [` #[doc = $s_int_type] /// `]. From a6e3e02d70708c6777e2b4090e12d7ee528fd1ac Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 3 Mar 2024 08:12:56 -0800 Subject: [PATCH 06/16] Update library/core/src/sync/atomic.rs Co-authored-by: Taiki Endo --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index aac0acbadbfc9..632f5f4be685d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -272,7 +272,7 @@ unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// -/// This type has the same size, alignment, and bit validity as a `*mut T`. +/// This type has the same size and bit validity as a `*mut T`. /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of pointers. Its size depends on the target pointer's size. From 804c0476575e891aa47131d67cbb3b6c21682abf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 27 Mar 2024 10:56:11 +0000 Subject: [PATCH 07/16] Load missing type of impl associated constant from trait definition --- compiler/rustc_hir_typeck/src/lib.rs | 18 +++++++++--- tests/ui/consts/missing_assoc_const_type.rs | 28 +++++++++++++++++++ .../ui/consts/missing_assoc_const_type.stderr | 8 ++++++ tests/ui/consts/missing_assoc_const_type2.rs | 21 ++++++++++++++ .../consts/missing_assoc_const_type2.stderr | 8 ++++++ .../typeck_type_placeholder_item.stderr | 23 +++++++-------- 6 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 tests/ui/consts/missing_assoc_const_type.rs create mode 100644 tests/ui/consts/missing_assoc_const_type.stderr create mode 100644 tests/ui/consts/missing_assoc_const_type2.rs create mode 100644 tests/ui/consts/missing_assoc_const_type2.stderr diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 0b67b37df29d8..f201bfddf4bb1 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -192,10 +192,20 @@ fn typeck_with_fallback<'tcx>( check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params); } else { let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty { - Some(fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - })) + if let Some(item) = tcx.opt_associated_item(def_id.into()) + && let ty::AssocKind::Const = item.kind + && let ty::ImplContainer = item.container + && let Some(trait_item) = item.trait_item_def_id + { + let args = + tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args; + Some(tcx.type_of(trait_item).instantiate(tcx, args)) + } else { + Some(fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + })) + } } else if let Node::AnonConst(_) = node { match tcx.parent_hir_node(id) { Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. }) diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs new file mode 100644 index 0000000000000..8d95e3dca633c --- /dev/null +++ b/tests/ui/consts/missing_assoc_const_type.rs @@ -0,0 +1,28 @@ +//! Test that we compute the right type for associated constants +//! of impls, even if the type is missing. We know it from the trait +//! declaration after all. + +trait Range { + const FIRST: u8; + const LAST: u8; +} + +struct TwoDigits; +impl Range for TwoDigits { + const FIRST: = 10; + //~^ ERROR: missing type for `const` item + const LAST: u8 = 99; +} + +const fn digits(x: u8) -> usize { + match x { + TwoDigits::FIRST..=TwoDigits::LAST => 0, + 0..=9 | 100..=255 => panic!(), + } +} + +const FOOMP: [(); { + digits(42) +}] = []; + +fn main() {} diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr new file mode 100644 index 0000000000000..28af1f0f321e6 --- /dev/null +++ b/tests/ui/consts/missing_assoc_const_type.stderr @@ -0,0 +1,8 @@ +error: missing type for `const` item + --> $DIR/missing_assoc_const_type.rs:12:17 + | +LL | const FIRST: = 10; + | ^ help: provide a type for the associated constant: `u8` + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/missing_assoc_const_type2.rs b/tests/ui/consts/missing_assoc_const_type2.rs new file mode 100644 index 0000000000000..baf236700a396 --- /dev/null +++ b/tests/ui/consts/missing_assoc_const_type2.rs @@ -0,0 +1,21 @@ +//! Test that we compute the right type for associated constants +//! of impls, even if the type is missing. We know it from the trait +//! declaration after all. + +trait Range { + const FIRST: u8; + const LAST: u8; +} + +struct TwoDigits; +impl Range for TwoDigits { + const FIRST: = 10; + //~^ ERROR: missing type + const LAST: u8 = 99; +} + +const FOOMP: [(); { + TwoDigits::FIRST as usize +}] = [(); 10]; + +fn main() {} diff --git a/tests/ui/consts/missing_assoc_const_type2.stderr b/tests/ui/consts/missing_assoc_const_type2.stderr new file mode 100644 index 0000000000000..1255ca2d102b5 --- /dev/null +++ b/tests/ui/consts/missing_assoc_const_type2.stderr @@ -0,0 +1,8 @@ +error: missing type for `const` item + --> $DIR/missing_assoc_const_type2.rs:12:17 + | +LL | const FIRST: = 10; + | ^ help: provide a type for the associated constant: `u8` + +error: aborting due to 1 previous error + diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 8bcad56916aa9..7977504dae1d6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -546,6 +546,15 @@ help: use type parameters instead LL | fn fn_test10(&self, _x : T) { } | +++ ~ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:194:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:217:31 | @@ -574,19 +583,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:209:14 | LL | const D: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:194:14 - | -LL | const D: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures error[E0046]: not all trait items implemented, missing: `F` --> $DIR/typeck_type_placeholder_item.rs:200:1 From d0eb9c86f1ec1d2f6c2c5c09abb31d2b3d3e7069 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 27 Mar 2024 11:12:21 +0000 Subject: [PATCH 08/16] move type inference for missing types on constants into its own method --- compiler/rustc_hir_typeck/src/lib.rs | 104 +++++++++++++++------------ 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index f201bfddf4bb1..55e86bbec1c48 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -191,52 +191,7 @@ fn typeck_with_fallback<'tcx>( check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params); } else { - let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty { - if let Some(item) = tcx.opt_associated_item(def_id.into()) - && let ty::AssocKind::Const = item.kind - && let ty::ImplContainer = item.container - && let Some(trait_item) = item.trait_item_def_id - { - let args = - tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args; - Some(tcx.type_of(trait_item).instantiate(tcx, args)) - } else { - Some(fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - })) - } - } else if let Node::AnonConst(_) = node { - match tcx.parent_hir_node(id) { - Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. }) - if anon_const.hir_id == id => - { - Some(fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - })) - } - Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => { - asm.operands.iter().find_map(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { - // Inline assembly constants must be integers. - Some(fcx.next_int_var()) - } - hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => { - Some(fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, - })) - } - _ => None, - }) - } - _ => None, - } - } else { - None - }; + let expected_type = infer_type_if_missing(body_ty, &fcx, node); let expected_type = expected_type.unwrap_or_else(fallback); let expected_type = fcx.normalize(body.value.span, expected_type); @@ -306,6 +261,63 @@ fn typeck_with_fallback<'tcx>( typeck_results } +fn infer_type_if_missing<'tcx>( + body_ty: Option<&hir::Ty<'tcx>>, + fcx: &FnCtxt<'_, 'tcx>, + node: Node<'tcx>, +) -> Option> { + let tcx = fcx.tcx; + let def_id = fcx.body_id; + let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty { + if let Some(item) = tcx.opt_associated_item(def_id.into()) + && let ty::AssocKind::Const = item.kind + && let ty::ImplContainer = item.container + && let Some(trait_item) = item.trait_item_def_id + { + let args = + tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args; + Some(tcx.type_of(trait_item).instantiate(tcx, args)) + } else { + Some(fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + })) + } + } else if let Node::AnonConst(_) = node { + let id = tcx.local_def_id_to_hir_id(def_id); + match tcx.parent_hir_node(id) { + Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. }) + if anon_const.hir_id == id => + { + Some(fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + })) + } + Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => { + asm.operands.iter().find_map(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { + // Inline assembly constants must be integers. + Some(fcx.next_int_var()) + } + hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => { + Some(fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + })) + } + _ => None, + }) + } + _ => None, + } + } else { + None + }; + expected_type +} + /// When `check_fn` is invoked on a coroutine (i.e., a body that /// includes yield), it returns back some information about the yield /// points. From 7786ee3c9240084ddb2b62d3f78cffce61462199 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 27 Mar 2024 11:13:34 +0000 Subject: [PATCH 09/16] Remove a call-site to `primary_body_of` as it is only interested in the body id --- compiler/rustc_hir_typeck/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 55e86bbec1c48..c135389ec9861 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -106,7 +106,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } if let Some(def_id) = def_id.as_local() { - primary_body_of(tcx.hir_node_by_def_id(def_id)).is_some() + tcx.hir_node_by_def_id(def_id).body_id().is_some() } else { false } From 86e750f0f777d78a108fa224731ef163b35f2309 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 27 Mar 2024 11:16:41 +0000 Subject: [PATCH 10/16] Inline `primary_body_of` into its sole call site --- compiler/rustc_hir_typeck/src/lib.rs | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c135389ec9861..00d3e262cc891 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -83,20 +83,6 @@ macro_rules! type_error_struct { }) } -/// If this `DefId` is a "primary tables entry", returns -/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`. -/// -/// If this function returns `Some`, then `typeck_results(def_id)` will -/// succeed; if it returns `None`, then `typeck_results(def_id)` may or -/// may not succeed. In some cases where this function returns `None` -/// (notably closures), `typeck_results(def_id)` would wind up -/// redirecting to the owning function. -fn primary_body_of( - node: Node<'_>, -) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> { - Some((node.body_id()?, node.ty(), node.fn_sig())) -} - fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". @@ -163,7 +149,7 @@ fn typeck_with_fallback<'tcx>( let span = tcx.hir().span(id); // Figure out what primary body this item has. - let (body_id, body_ty, fn_sig) = primary_body_of(node).unwrap_or_else(|| { + let body_id = node.body_id().unwrap_or_else(|| { span_bug!(span, "can't type-check body of {:?}", def_id); }); let body = tcx.hir().body(body_id); @@ -176,7 +162,7 @@ fn typeck_with_fallback<'tcx>( } let mut fcx = FnCtxt::new(&inh, param_env, def_id); - if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { let fn_sig = if decl.output.get_infer_ret_ty().is_some() { fcx.lowerer().lower_fn_ty(id, header.unsafety, header.abi, decl, None, None) } else { @@ -191,7 +177,7 @@ fn typeck_with_fallback<'tcx>( check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params); } else { - let expected_type = infer_type_if_missing(body_ty, &fcx, node); + let expected_type = infer_type_if_missing(&fcx, node); let expected_type = expected_type.unwrap_or_else(fallback); let expected_type = fcx.normalize(body.value.span, expected_type); @@ -261,14 +247,10 @@ fn typeck_with_fallback<'tcx>( typeck_results } -fn infer_type_if_missing<'tcx>( - body_ty: Option<&hir::Ty<'tcx>>, - fcx: &FnCtxt<'_, 'tcx>, - node: Node<'tcx>, -) -> Option> { +fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option> { let tcx = fcx.tcx; let def_id = fcx.body_id; - let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty { + let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() { if let Some(item) = tcx.opt_associated_item(def_id.into()) && let ty::AssocKind::Const = item.kind && let ty::ImplContainer = item.container From 0cd9708de60fb0f92561e0a6ed0a8c5991fd871d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Tue, 26 Mar 2024 18:59:03 +0300 Subject: [PATCH 11/16] Delegation: fix ICE on wrong instantiation --- .../src/hir_ty_lowering/mod.rs | 11 ++ tests/ui/delegation/bad-resolve.rs | 10 +- tests/ui/delegation/bad-resolve.stderr | 37 +---- .../duplicate-definition-inside-trait-impl.rs | 2 +- ...licate-definition-inside-trait-impl.stderr | 11 +- .../explicit-paths-in-traits-pass.rs | 2 +- .../explicit-paths-in-traits-pass.stderr | 11 -- tests/ui/delegation/explicit-paths-pass.rs | 13 +- .../ui/delegation/explicit-paths-pass.stderr | 11 -- .../explicit-paths-signature-pass.rs | 2 +- .../explicit-paths-signature-pass.stderr | 11 -- tests/ui/delegation/explicit-paths.rs | 79 ++++++++-- tests/ui/delegation/explicit-paths.stderr | 137 +++++++++++++++--- tests/ui/delegation/not-supported.rs | 2 +- tests/ui/delegation/not-supported.stderr | 11 +- tests/ui/delegation/parse.rs | 2 +- tests/ui/delegation/parse.stderr | 11 -- tests/ui/delegation/target-expr-pass.rs | 2 +- tests/ui/delegation/target-expr-pass.stderr | 11 +- tests/ui/delegation/target-expr.rs | 6 +- tests/ui/delegation/target-expr.stderr | 31 +++- 21 files changed, 236 insertions(+), 177 deletions(-) delete mode 100644 tests/ui/delegation/explicit-paths-in-traits-pass.stderr delete mode 100644 tests/ui/delegation/explicit-paths-pass.stderr delete mode 100644 tests/ui/delegation/explicit-paths-signature-pass.stderr delete mode 100644 tests/ui/delegation/parse.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a83b5b78f9cc0..8886a78c6ecdc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2212,6 +2212,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { try_emit("delegation with early bound generics"); } + // There is no way to instantiate `Self` param for caller if + // 1. callee is a trait method + // 2. delegation item isn't an associative item + if let DefKind::AssocFn = self.tcx().def_kind(sig_id) + && let DefKind::Fn = self.tcx().def_kind(self.item_def_id()) + && self.tcx().associated_item(sig_id).container + == ty::AssocItemContainer::TraitContainer + { + try_emit("delegation to a trait method from a free function"); + } + if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes { try_emit("delegation to async functions"); } diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs index df456f94507be..d2723dc32e043 100644 --- a/tests/ui/delegation/bad-resolve.rs +++ b/tests/ui/delegation/bad-resolve.rs @@ -1,5 +1,5 @@ #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] trait Trait { const C: u32 = 0; @@ -34,14 +34,6 @@ impl Trait for S { reuse foo { &self.0 } //~^ ERROR cannot find function `foo` in this scope - reuse F::foo { &self.0 } - //~^ ERROR cannot find function `foo` in `F` - //~| ERROR duplicate definitions with name `foo` -} - -impl S { - reuse F::foo { &self.0 } - //~^ ERROR cannot find function `foo` in `F` } fn main() {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index d520663731002..f669ac3730e26 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -25,18 +25,6 @@ LL | reuse ::baz; | | help: there is an associated function with a similar name: `bar` | not a member of trait `Trait` -error[E0201]: duplicate definitions with name `foo`: - --> $DIR/bad-resolve.rs:37:5 - | -LL | fn foo(&self, x: i32) -> i32 { x } - | ---------------------------------- item in trait -... -LL | reuse foo { &self.0 } - | --------------------- previous definition here -LL | -LL | reuse F::foo { &self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition - error[E0423]: expected function, found associated constant `Trait::C` --> $DIR/bad-resolve.rs:24:11 | @@ -66,27 +54,6 @@ error[E0425]: cannot find function `foo` in this scope LL | reuse foo { &self.0 } | ^^^ not found in this scope -error[E0425]: cannot find function `foo` in `F` - --> $DIR/bad-resolve.rs:37:14 - | -LL | reuse F::foo { &self.0 } - | ^^^ not found in `F` - -error[E0425]: cannot find function `foo` in `F` - --> $DIR/bad-resolve.rs:43:14 - | -LL | reuse F::foo { &self.0 } - | ^^^ not found in `F` - -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-resolve.rs:1:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0046]: not all trait items implemented, missing: `Type` --> $DIR/bad-resolve.rs:22:1 | @@ -96,7 +63,7 @@ LL | type Type; LL | impl Trait for S { | ^^^^^^^^^^^^^^^^ missing `Type` in implementation -error: aborting due to 11 previous errors; 1 warning emitted +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0046, E0201, E0324, E0407, E0423, E0425, E0575, E0576. +Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0575, E0576. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs index bd685b40b2ff5..9c7afcef3ec12 100644 --- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs @@ -1,5 +1,5 @@ #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] trait Trait { fn foo(&self) -> u32 { 0 } diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr index a5f9e6ad0bf47..a0f157800cb59 100644 --- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr @@ -9,15 +9,6 @@ LL | reuse to_reuse::foo { self } LL | reuse Trait::foo; | ^^^^^^^^^^^^^^^^^ duplicate definition -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/duplicate-definition-inside-trait-impl.rs:1:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - -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 E0201`. diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.rs b/tests/ui/delegation/explicit-paths-in-traits-pass.rs index 4abcc18b9b2cf..7d281ad150a03 100644 --- a/tests/ui/delegation/explicit-paths-in-traits-pass.rs +++ b/tests/ui/delegation/explicit-paths-in-traits-pass.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] trait ToReuse { fn foo(&self, x: i32) -> i32 { x } diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.stderr b/tests/ui/delegation/explicit-paths-in-traits-pass.stderr deleted file mode 100644 index 8a320b44e63db..0000000000000 --- a/tests/ui/delegation/explicit-paths-in-traits-pass.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/explicit-paths-in-traits-pass.rs:3:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs index 140605a2bc5bf..fada793bd118c 100644 --- a/tests/ui/delegation/explicit-paths-pass.rs +++ b/tests/ui/delegation/explicit-paths-pass.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] trait Trait { fn bar(&self, x: i32) -> i32 { x } @@ -10,7 +10,6 @@ trait Trait { } fn static_method(x: i32) -> i32 { x } fn static_method2(x: i32, y: i32) -> i32 { x + y } - fn baz<'a>(&self, x: &'a i32) -> &'a i32 { x } } struct F; @@ -29,11 +28,9 @@ impl Trait for S { reuse Trait::description { &self.0 } reuse ::static_method; reuse ::static_method2 { S::static_method(self) } - reuse Trait::baz { &self.0 } } impl S { - reuse Trait::baz { &self.0 } reuse ::static_method { to_reuse::foo(self) } } @@ -49,16 +46,8 @@ fn main() { assert_eq!(42, ::static_method(42)); assert_eq!(21, S::static_method2(10, 10)); - reuse ::static_method; - reuse ::static_method2 { static_method(self) } #[inline] reuse to_reuse::foo; - assert_eq!(42, static_method(42)); - assert_eq!(21, static_method2(10, 10)); assert_eq!(43, foo(42)); assert_eq!(15, zero_args()); - - let x: i32 = 15; - assert_eq!(&x, ::baz(&s, &x)); - assert_eq!(&x, S::baz(&s, &x)); } diff --git a/tests/ui/delegation/explicit-paths-pass.stderr b/tests/ui/delegation/explicit-paths-pass.stderr deleted file mode 100644 index 6d25fb4a5a57d..0000000000000 --- a/tests/ui/delegation/explicit-paths-pass.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/explicit-paths-pass.rs:3:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs index b53e577992466..8c16ad92393c9 100644 --- a/tests/ui/delegation/explicit-paths-signature-pass.rs +++ b/tests/ui/delegation/explicit-paths-signature-pass.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] mod to_reuse { use crate::S; diff --git a/tests/ui/delegation/explicit-paths-signature-pass.stderr b/tests/ui/delegation/explicit-paths-signature-pass.stderr deleted file mode 100644 index 6c81a2ea0af73..0000000000000 --- a/tests/ui/delegation/explicit-paths-signature-pass.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/explicit-paths-signature-pass.rs:3:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs index 1feaaa73f79e8..a91ca4cb931ed 100644 --- a/tests/ui/delegation/explicit-paths.rs +++ b/tests/ui/delegation/explicit-paths.rs @@ -1,25 +1,84 @@ #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] trait Trait { - fn bar(&self) -> i32 { 42 } + fn foo1(&self, x: i32) -> i32 { x } + fn foo2(x: i32) -> i32 { x } } struct F; impl Trait for F {} - struct S(F); -impl Trait for S { - reuse ::bar; - //~^ ERROR mismatched types +pub mod to_reuse { + pub fn foo3() {} +} + +impl F { + fn foo4(&self) {} +} + +mod fn_to_other { + use super::*; + + reuse Trait::foo1; + //~^ ERROR delegation to a trait method from a free function is not supported yet + reuse ::foo2; + //~^ ERROR delegation to a trait method from a free function is not supported yet + reuse to_reuse::foo3; + reuse S::foo4; + //~^ ERROR cannot find function `foo4` in `S` +} + +mod inherent_impl_assoc_fn_to_other { + use crate::*; + + impl S { + reuse Trait::foo1 { &self.0 } + reuse ::foo2; + reuse to_reuse::foo3; + reuse F::foo4 { &self.0 } + //~^ ERROR cannot find function `foo4` in `F` + } +} + +mod trait_impl_assoc_fn_to_other { + use crate::*; + + impl Trait for S { + reuse Trait::foo1 { &self.0 } + reuse ::foo2; + reuse to_reuse::foo3; + //~^ ERROR method `foo3` is not a member of trait `Trait` + reuse F::foo4 { &self.0 } + //~^ ERROR method `foo4` is not a member of trait `Trait` + //~| ERROR cannot find function `foo4` in `F` + } +} + +mod trait_assoc_fn_to_other { + use crate::*; + + trait Trait2 : Trait { + reuse ::foo1 { self } + //~^ ERROR mismatched types + reuse ::foo2; + reuse to_reuse::foo3; + reuse F::foo4 { &F } + //~^ ERROR cannot find function `foo4` in `F` + } } -struct S2(F); +mod type_mismatch { + use crate::*; -impl Trait for S2 { - reuse ::bar { &self.0 } - //~^ ERROR mismatched types + struct S2; + impl Trait for S { + //~^ ERROR conflicting implementations of trait `Trait` for type `S` + reuse ::foo1; + //~^ ERROR mismatched types + //~| ERROR the trait bound `S2: Trait` is not satisfied + } } fn main() {} diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr index 2994b2390dedf..30891c94c0e98 100644 --- a/tests/ui/delegation/explicit-paths.stderr +++ b/tests/ui/delegation/explicit-paths.stderr @@ -1,38 +1,129 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/explicit-paths.rs:1:12 +error[E0407]: method `foo3` is not a member of trait `Trait` + --> $DIR/explicit-paths.rs:51:9 | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ +LL | reuse to_reuse::foo3; + | ^^^^^^^^^^^^^^^^----^ + | | | + | | help: there is an associated function with a similar name: `foo1` + | not a member of trait `Trait` + +error[E0407]: method `foo4` is not a member of trait `Trait` + --> $DIR/explicit-paths.rs:53:9 + | +LL | reuse F::foo4 { &self.0 } + | ^^^^^^^^^----^^^^^^^^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo1` + | not a member of trait `Trait` + +error[E0425]: cannot find function `foo4` in `S` + --> $DIR/explicit-paths.rs:29:14 + | +LL | reuse S::foo4; + | ^^^^ not found in `S` + +error[E0425]: cannot find function `foo4` in `F` + --> $DIR/explicit-paths.rs:40:18 + | +LL | reuse F::foo4 { &self.0 } + | ^^^^ not found in `F` + | +note: function `fn_to_other::foo4` exists but is inaccessible + --> $DIR/explicit-paths.rs:29:5 + | +LL | reuse S::foo4; + | ^^^^^^^^^^^^^^ not accessible + +error[E0425]: cannot find function `foo4` in `F` + --> $DIR/explicit-paths.rs:53:18 + | +LL | reuse F::foo4 { &self.0 } + | ^^^^ not found in `F` + | +note: function `fn_to_other::foo4` exists but is inaccessible + --> $DIR/explicit-paths.rs:29:5 + | +LL | reuse S::foo4; + | ^^^^^^^^^^^^^^ not accessible + +error[E0425]: cannot find function `foo4` in `F` + --> $DIR/explicit-paths.rs:67:18 + | +LL | reuse F::foo4 { &F } + | ^^^^ not found in `F` + | +note: function `fn_to_other::foo4` exists but is inaccessible + --> $DIR/explicit-paths.rs:29:5 | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default +LL | reuse S::foo4; + | ^^^^^^^^^^^^^^ not accessible + +error[E0119]: conflicting implementations of trait `Trait` for type `S` + --> $DIR/explicit-paths.rs:76:5 + | +LL | impl Trait for S { + | ---------------- first implementation here +... +LL | impl Trait for S { + | ^^^^^^^^^^^^^^^^ conflicting implementation for `S` + +error: delegation to a trait method from a free function is not supported yet + --> $DIR/explicit-paths.rs:24:18 + | +LL | fn foo1(&self, x: i32) -> i32 { x } + | ----------------------------- callee defined here +... +LL | reuse Trait::foo1; + | ^^^^ + +error: delegation to a trait method from a free function is not supported yet + --> $DIR/explicit-paths.rs:26:25 + | +LL | fn foo2(x: i32) -> i32 { x } + | ---------------------- callee defined here +... +LL | reuse ::foo2; + | ^^^^ error[E0308]: mismatched types - --> $DIR/explicit-paths.rs:14:25 + --> $DIR/explicit-paths.rs:63:36 | -LL | reuse ::bar; - | --------------^^^ - | | | - | | expected `&F`, found `&S` - | arguments to this function are incorrect +LL | trait Trait2 : Trait { + | -------------------- found this type parameter +LL | reuse ::foo1 { self } + | ^^^^ expected `&F`, found `&Self` | = note: expected reference `&F` - found reference `&S` -note: method defined here - --> $DIR/explicit-paths.rs:5:8 + found reference `&Self` + +error[E0277]: the trait bound `S2: Trait` is not satisfied + --> $DIR/explicit-paths.rs:78:16 | -LL | fn bar(&self) -> i32 { 42 } - | ^^^ ----- +LL | reuse ::foo1; + | ^^ the trait `Trait` is not implemented for `S2` + | + = help: the following other types implement trait `Trait`: + F + S error[E0308]: mismatched types - --> $DIR/explicit-paths.rs:21:32 + --> $DIR/explicit-paths.rs:78:30 | -LL | reuse ::bar { &self.0 } - | ^^^^^^^ expected `&S2`, found `&F` +LL | reuse ::foo1; + | ---------------^^^^ + | | | + | | expected `&S2`, found `&S` + | arguments to this function are incorrect | = note: expected reference `&S2` - found reference `&F` + found reference `&S` +note: method defined here + --> $DIR/explicit-paths.rs:5:8 + | +LL | fn foo1(&self, x: i32) -> i32 { x } + | ^^^^ ----- -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0119, E0277, E0308, E0407, E0425. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs index 23081b1e1fc8b..9dccb12b57adb 100644 --- a/tests/ui/delegation/not-supported.rs +++ b/tests/ui/delegation/not-supported.rs @@ -1,6 +1,6 @@ #![feature(c_variadic)] #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] mod generics { trait GenericTrait { diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index 324b79f3c535a..f6c49366899c1 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -1,12 +1,3 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/not-supported.rs:2:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - error: delegation with early bound generics is not supported yet --> $DIR/not-supported.rs:16:29 | @@ -178,7 +169,7 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error: aborting due to 19 previous errors; 1 warning emitted +error: aborting due to 19 previous errors Some errors have detailed explanations: E0049, E0195. For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/delegation/parse.rs b/tests/ui/delegation/parse.rs index 5e8026c553212..72b00bf6e0d53 100644 --- a/tests/ui/delegation/parse.rs +++ b/tests/ui/delegation/parse.rs @@ -2,7 +2,7 @@ #![feature(decl_macro)] #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] macro_rules! reuse { {} => {} } diff --git a/tests/ui/delegation/parse.stderr b/tests/ui/delegation/parse.stderr deleted file mode 100644 index 1e420ceeec7f1..0000000000000 --- a/tests/ui/delegation/parse.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/parse.rs:4:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs index 1f2edf0dc13fc..9e326a19b8f1c 100644 --- a/tests/ui/delegation/target-expr-pass.rs +++ b/tests/ui/delegation/target-expr-pass.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(fn_delegation)] -//~^ WARN the feature `fn_delegation` is incomplete +#![allow(incomplete_features)] mod to_reuse { pub fn foo(x: i32) -> i32 { x } diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr index dd1f3a14e0bd8..c8d73ec6e5aa6 100644 --- a/tests/ui/delegation/target-expr-pass.stderr +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -1,12 +1,3 @@ -warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/target-expr-pass.rs:3:12 - | -LL | #![feature(fn_delegation)] - | ^^^^^^^^^^^^^ - | - = note: see issue #118212 for more information - = note: `#[warn(incomplete_features)]` on by default - warning: trait `Trait` is never used --> $DIR/target-expr-pass.rs:17:7 | @@ -27,5 +18,5 @@ warning: struct `S` is never constructed LL | struct S(F); | ^ -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs index b9c6fe92810b1..fd7ea943b9d5e 100644 --- a/tests/ui/delegation/target-expr.rs +++ b/tests/ui/delegation/target-expr.rs @@ -14,8 +14,9 @@ fn foo(x: i32) -> i32 { x } fn bar(_: T) { reuse Trait::static_method { - //~^ ERROR delegation with early bound generics is not supported yet - //~| ERROR mismatched types + //~^ ERROR delegation to a trait method from a free function is not supported yet + //~| ERROR delegation with early bound generics is not supported yet + //~| ERROR mismatched types let _ = T::Default(); //~^ ERROR can't use generic parameters from outer item } @@ -24,6 +25,7 @@ fn bar(_: T) { fn main() { let y = 0; reuse ::static_method { + //~^ ERROR delegation to a trait method from a free function is not supported yet let x = y; //~^ ERROR can't capture dynamic environment in a fn item foo(self); diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index da0fac2f5e46b..b30f0c474c68b 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/target-expr.rs:19:17 + --> $DIR/target-expr.rs:20:17 | LL | fn bar(_: T) { | - type parameter from outer item @@ -10,7 +10,7 @@ LL | let _ = T::Default(); | ^^^^^^^^^^ use of generic parameter from outer item error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/target-expr.rs:27:17 + --> $DIR/target-expr.rs:29:17 | LL | let x = y; | ^ @@ -18,7 +18,7 @@ LL | let x = y; = help: use the `|| { ... }` closure form instead error[E0424]: expected value, found module `self` - --> $DIR/target-expr.rs:34:5 + --> $DIR/target-expr.rs:36:5 | LL | fn main() { | ---- this function can't have a `self` parameter @@ -27,13 +27,13 @@ LL | self.0; | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find value `x` in this scope - --> $DIR/target-expr.rs:36:13 + --> $DIR/target-expr.rs:38:13 | LL | let z = x; | ^ | help: the binding `x` is available in a different scope in the same function - --> $DIR/target-expr.rs:27:13 + --> $DIR/target-expr.rs:29:13 | LL | let x = y; | ^ @@ -47,6 +47,24 @@ LL | fn static_method(x: i32) -> i32 { x } LL | reuse Trait::static_method { | ^^^^^^^^^^^^^ +error: delegation to a trait method from a free function is not supported yet + --> $DIR/target-expr.rs:16:18 + | +LL | fn static_method(x: i32) -> i32 { x } + | ------------------------------- callee defined here +... +LL | reuse Trait::static_method { + | ^^^^^^^^^^^^^ + +error: delegation to a trait method from a free function is not supported yet + --> $DIR/target-expr.rs:27:25 + | +LL | fn static_method(x: i32) -> i32 { x } + | ------------------------------- callee defined here +... +LL | reuse ::static_method { + | ^^^^^^^^^^^^^ + error[E0308]: mismatched types --> $DIR/target-expr.rs:16:32 | @@ -54,12 +72,13 @@ LL | reuse Trait::static_method { | ________________________________^ LL | | LL | | +LL | | LL | | let _ = T::Default(); LL | | LL | | } | |_____^ expected `i32`, found `()` -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434. For more information about an error, try `rustc --explain E0308`. From 3157114f0b4b28caad0d593a0cc5d8b04d02a29c Mon Sep 17 00:00:00 2001 From: xiaoxiangxianzi Date: Wed, 27 Mar 2024 21:19:17 +0800 Subject: [PATCH 12/16] chore: fix some comments Signed-off-by: xiaoxiangxianzi --- INSTALL.md | 4 ++-- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 2 +- compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- library/core/src/pin.rs | 2 +- tests/rustdoc-gui/target.goml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index a23ea4f1eeeb2..9619ec2ce5cfa 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -151,8 +151,8 @@ toolchain. directory and uncomment the line `MSYS2_PATH_TYPE=inherit`. You could install and use MSYS2's version of git instead with `pacman`, - however this is not recommended as it's excrutiatingly slow, and not frequently - tested for compatability. + however this is not recommended as it's excruciatingly slow, and not frequently + tested for compatibility. 3. Start a MINGW64 or MINGW32 shell (depending on whether you want 32-bit or 64-bit Rust) either from your start menu, or by running `mingw64.exe` diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 8bd8b6ac14475..6eff70410cbbb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -75,7 +75,7 @@ pub(crate) struct FixupContext { } /// The default amount of fixing is minimal fixing. Fixups should be turned on -/// in a targetted fashion where needed. +/// in a targeted fashion where needed. impl Default for FixupContext { fn default() -> Self { FixupContext { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a206aac0467f4..dcf84a2e036be 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -592,7 +592,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - // If the region is live at at least one location in the promoted MIR, + // If the region is live at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region // at the location provided as an argument to this method // 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 098a6201c4ea3..4283ebc99d264 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -409,7 +409,7 @@ fn const_validate_mplace<'mir, 'tcx>( } }; ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode) - // Instead of just reporting the `InterpError` via the usual machinery, we give a more targetted + // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted // error about the validation failure. .map_err(|error| report_validation_error(&ecx, error, alloc_id))?; inner = true; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 8c35da3ac7b7d..d9d36f5299b58 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -11,7 +11,7 @@ use super::HirTyLowerer; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Prohibit or lint against *bare* trait object types depending on the edition. /// - /// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`. + /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. pub(super) fn prohibit_or_lint_bare_trait_object_ty( &self, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7e317c3df1465..18fb858c84cf6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2768,7 +2768,7 @@ impl<'a> Parser<'a> { }; return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) { // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the - // parser state and emit a targetted suggestion. + // parser state and emit a targeted suggestion. let span = vec![start_span, self.token.span]; let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span)); self.bump(); // ) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index d14cac9afb56d..e843a5d5790d2 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -806,7 +806,7 @@ //! //! As a consequence, the struct *must not* be [`#[repr(packed)]`][packed]. //! -//! 3. *Structural Notice of Destruction.* You must uphold the the +//! 3. *Structural Notice of Destruction.* You must uphold the //! [`Drop` guarantee][drop-guarantee]: once your struct is pinned, the struct's storage cannot //! be re-used without calling the structurally-pinned fields' destructors, as well. //! diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml index c5e7f813dd194..26071df8d044e 100644 --- a/tests/rustdoc-gui/target.goml +++ b/tests/rustdoc-gui/target.goml @@ -1,4 +1,4 @@ -// Check that the targetted element has the expected styles. +// Check that the targeted element has the expected styles. go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html#method.a_method" show-text: true From cc4a1f42e64d1061bb59e349e999b925e1e85b99 Mon Sep 17 00:00:00 2001 From: Vagelis Prokopiou Date: Wed, 27 Mar 2024 17:26:18 +0200 Subject: [PATCH 13/16] Some wording improvement --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 8b3a9e82aad18..9017ba7971463 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -385,7 +385,7 @@ impl File { /// See the [`OpenOptions::open`] function for more details. /// /// See also [`std::fs::write()`][self::write] for a simple function to - /// create a file with a given data. + /// create a file with some given data. /// /// # Examples /// @@ -1036,7 +1036,7 @@ impl OpenOptions { /// [`OpenOptions::append`] access must be used. /// /// See also [`std::fs::write()`][self::write] for a simple function to - /// create a file with a given data. + /// create a file with some given data. /// /// # Examples /// From 336ff42367aa375bba85bf5dbbea535b3c04d929 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 27 Mar 2024 10:25:56 -0700 Subject: [PATCH 14/16] `num::NonZero::get` can be 1 transmute instead of 3 --- library/core/src/num/nonzero.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c65ffbb98f2ff..1171407c07a3f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -20,7 +20,15 @@ use super::{IntErrorKind, ParseIntError}; /// /// # Safety /// -/// Types implementing this trait must be primitves that are valid when zeroed. +/// Types implementing this trait must be primitives that are valid when zeroed. +/// +/// The associated `Self::NonZeroInner` type must have the same size+align as `Self`, +/// but with a niche and bit validity making it so the following `transmutes` are sound: +/// +/// - `Self::NonZeroInner` to `Option` +/// - `Option` to `Self` +/// +/// (And, consequently, `Self::NonZeroInner` to `Self`.) #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -434,17 +442,11 @@ where // of some not-inlined function, LLVM don't have range metadata // to understand that the value cannot be zero. // - // SAFETY: `Self` is guaranteed to have the same layout as `Option`. - match unsafe { intrinsics::transmute_unchecked(self) } { - None => { - // SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable. - unsafe { intrinsics::unreachable() } - } - Some(Self(inner)) => { - // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`. - unsafe { intrinsics::transmute_unchecked(inner) } - } - } + // For now, using the transmute `assume`s the range at runtime. + // + // SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity + // of `.0` is such that this transmute is sound. + unsafe { intrinsics::transmute_unchecked(self) } } } From 0b860818e6fe937f09680a6434a9d6b0e1e44dcb Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Mon, 25 Mar 2024 21:39:26 -0700 Subject: [PATCH 15/16] CFI: Fix drop and drop_in_place Fix drop and drop_in_place by transforming self of drop and drop_in_place methods into Drop trait objects. --- .../src/typeid/typeid_itanium_cxx_abi.rs | 32 +++++++++++++++++-- ...tadata-id-itanium-cxx-abi-drop-in-place.rs | 27 ++++++++++++++++ .../kcfi/emit-type-metadata-trait-objects.rs | 2 ++ tests/ui/sanitizer/cfi-drop-in-place.rs | 20 ++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs create mode 100644 tests/ui/sanitizer/cfi-drop-in-place.rs diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 3101015281b82..b41769b4b8f94 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -1112,8 +1112,36 @@ pub fn typeid_for_instance<'tcx>( mut instance: Instance<'tcx>, options: TypeIdOptions, ) -> String { - if matches!(instance.def, ty::InstanceDef::Virtual(..)) { - instance.args = strip_receiver_auto(tcx, instance.args) + if (matches!(instance.def, ty::InstanceDef::Virtual(..)) + && Some(instance.def_id()) == tcx.lang_items().drop_in_place_fn()) + || matches!(instance.def, ty::InstanceDef::DropGlue(..)) + { + // Adjust the type ids of DropGlues + // + // DropGlues may have indirect calls to one or more given types drop function. Rust allows + // for types to be erased to any trait object and retains the drop function for the original + // type, which means at the indirect call sites in DropGlues, when typeid_for_fnabi is + // called a second time, it only has information after type erasure and it could be a call + // on any arbitrary trait object. Normalize them to a synthesized Drop trait object, both on + // declaration/definition, and during code generation at call sites so they have the same + // type id and match. + // + // FIXME(rcvalle): This allows a drop call on any trait object to call the drop function of + // any other type. + // + let def_id = tcx + .lang_items() + .drop_trait() + .unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item")); + let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { + def_id: def_id, + args: List::empty(), + }); + 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 matches!(instance.def, ty::InstanceDef::Virtual(..)) { + instance.args = strip_receiver_auto(tcx, instance.args); } if let Some(impl_id) = tcx.impl_of_method(instance.def_id()) diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs new file mode 100644 index 0000000000000..3ec1988edd6e8 --- /dev/null +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs @@ -0,0 +1,27 @@ +// Verifies that type metadata identifiers for drop functions are emitted correctly. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static + +#![crate_type="lib"] + +// CHECK-LABEL: define{{.*}}4core3ptr47drop_in_place$LT$dyn$u20$core..marker..Send$GT$ +// CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +// CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE") + +struct EmptyDrop; +// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + +struct NonEmptyDrop; + +impl Drop for NonEmptyDrop { + fn drop(&mut self) {} + // CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}NonEmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +pub fn foo() { + let _ = Box::new(EmptyDrop) as Box; + let _ = Box::new(NonEmptyDrop) as Box; +} + +// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE"} diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs index f08c9e6702ed9..f9c7cca39898d 100644 --- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs @@ -29,6 +29,8 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b trait Freeze { } #[lang="drop_in_place"] fn drop_in_place_fn() { } +#[lang="drop"] +trait Drop { fn drop(&mut self); } pub trait Trait1 { fn foo(&self); diff --git a/tests/ui/sanitizer/cfi-drop-in-place.rs b/tests/ui/sanitizer/cfi-drop-in-place.rs new file mode 100644 index 0000000000000..8ce2c43260261 --- /dev/null +++ b/tests/ui/sanitizer/cfi-drop-in-place.rs @@ -0,0 +1,20 @@ +// Verifies that drops can be called on arbitrary trait objects. +// +// FIXME(#122848): Remove only-linux when fixed. +//@ only-linux +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Copt-level=0 -Cprefer-dynamic=off -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ run-pass + +struct EmptyDrop; + +struct NonEmptyDrop; + +impl Drop for NonEmptyDrop { + fn drop(&mut self) {} +} + +fn main() { + let _ = Box::new(EmptyDrop) as Box; + let _ = Box::new(NonEmptyDrop) as Box; +} From df4eec891d1cc25c4ae5f47d94e4b0634862aa4b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:54:31 +0100 Subject: [PATCH 16/16] Let nils know about changes to target docs --- triagebot.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 2bcc77ae43323..1eec366eacb95 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -709,6 +709,9 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] [mentions."src/doc/unstable-book/src/compiler-flags/check-cfg.md"] cc = ["@Urgau"] +[mentions."src/doc/rustc/src/platform-support"] +cc = ["@Nilstrieb"] + [mentions."tests/codegen/sanitizer"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]