From 483f13ce913b7ceaeae9173d21cd3dc343f6dbc1 Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Sun, 21 Apr 2024 10:41:04 -0400 Subject: [PATCH 1/9] Make sure that the method resolution matches in note_source_of_type_mismatch_constraint --- compiler/rustc_hir_typeck/src/demand.rs | 33 +++++++++++++++---- tests/crashes/118185.rs | 26 --------------- ...hod-lookup-returns-sig-with-fewer-args.rs} | 5 ++- ...-lookup-returns-sig-with-fewer-args.stderr | 17 ++++++++++ 4 files changed, 46 insertions(+), 35 deletions(-) delete mode 100644 tests/crashes/118185.rs rename tests/{crashes/118185-2.rs => ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs} (85%) create mode 100644 tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d6d22a43fe0b8..ed81ed640361a 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -377,8 +377,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else { return false; }; - let possible_rcvr_ty = expr_finder.uses.iter().find_map(|binding| { + let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| { let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?; + if possible_rcvr_ty.is_ty_var() { + return None; + } // Fudge the receiver, so we can do new inference on it. let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger); let method = self @@ -390,6 +393,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { binding, ) .ok()?; + // Make sure we select the same method that we started with... + if Some(method.def_id) + != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id) + { + return None; + } // Unify the method signature with our incompatible arg, to // do inference in the *opposite* direction and to find out // what our ideal rcvr ty would look like. @@ -460,6 +469,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) else { continue; }; + // Make sure we select the same method that we started with... + if Some(method.def_id) + != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) + { + continue; + } let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger); let ideal_method = self @@ -509,13 +524,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // blame arg, if possible. Don't do this if we're coming from // arg mismatch code, because we'll possibly suggest a mutually // incompatible fix at the original mismatch site. + // HACK(compiler-errors): We don't actually consider the implications + // of our inference guesses in `emit_type_mismatch_suggestions`, so + // only suggest things when we know our type error is precisely due to + // a type mismatch, and not via some projection or something. See #116155. if matches!(source, TypeMismatchSource::Ty(_)) && let Some(ideal_method) = ideal_method - && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) - // HACK(compiler-errors): We don't actually consider the implications - // of our inference guesses in `emit_type_mismatch_suggestions`, so - // only suggest things when we know our type error is precisely due to - // a type mismatch, and not via some projection or something. See #116155. + && Some(ideal_method.def_id) + == self + .typeck_results + .borrow() + .type_dependent_def_id(parent_expr.hir_id) + && let ideal_arg_ty = + self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) && !ideal_arg_ty.has_non_region_infer() { self.emit_type_mismatch_suggestions( diff --git a/tests/crashes/118185.rs b/tests/crashes/118185.rs deleted file mode 100644 index c3a29c3a3f54a..0000000000000 --- a/tests/crashes/118185.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ known-bug: #118185 - -fn main() { - let target: Target = create_target(); - target.get(0); // correct arguments work - target.get(10.0); // CRASH HERE -} - -// must be generic -fn create_target<T>() -> T { - unimplemented!() -} - -// unimplemented trait, but contains function with the same name -pub trait RandomTrait { - fn get(&mut self); // but less arguments -} - -struct Target; - -impl Target { - // correct function with arguments - pub fn get(&self, data: i32) { - unimplemented!() - } -} diff --git a/tests/crashes/118185-2.rs b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs similarity index 85% rename from tests/crashes/118185-2.rs rename to tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs index c3a29c3a3f54a..fd41beecb0a2a 100644 --- a/tests/crashes/118185-2.rs +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs @@ -1,9 +1,8 @@ -//@ known-bug: #118185 - fn main() { let target: Target = create_target(); target.get(0); // correct arguments work - target.get(10.0); // CRASH HERE + target.get(10.0); // (used to crash here) + //~^ ERROR mismatched types } // must be generic diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr new file mode 100644 index 0000000000000..0f86916fcdae4 --- /dev/null +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:16 + | +LL | target.get(10.0); // (used to crash here) + | --- ^^^^ expected `i32`, found floating-point number + | | + | arguments to this method are incorrect + | +note: method defined here + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:22:12 + | +LL | pub fn get(&self, data: i32) { + | ^^^ --------- + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 75f57670b03a33dd165685fe1f252969ef5c16ea Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Wed, 8 May 2024 17:22:35 +0200 Subject: [PATCH 2/9] miri: rename intrinsic_fallback_checks_ub to intrinsic_fallback_is_spec --- library/core/src/intrinsics.rs | 10 +++++----- src/tools/miri/src/intrinsics/mod.rs | 6 +++--- .../tests/fail/intrinsic_fallback_checks_ub.stderr | 14 -------------- ..._checks_ub.rs => intrinsic_fallback_is_spec.rs} | 2 +- .../tests/fail/intrinsic_fallback_is_spec.stderr | 14 ++++++++++++++ 5 files changed, 23 insertions(+), 23 deletions(-) delete mode 100644 src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr rename src/tools/miri/tests/fail/{intrinsic_fallback_checks_ub.rs => intrinsic_fallback_is_spec.rs} (75%) create mode 100644 src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d1450bf12ce72..1027d48364002 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -987,7 +987,7 @@ pub const unsafe fn assume(b: bool) { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] pub const fn likely(b: bool) -> bool { b } @@ -1007,7 +1007,7 @@ pub const fn likely(b: bool) -> bool { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] pub const fn unlikely(b: bool) -> bool { b } @@ -2471,7 +2471,7 @@ extern "rust-intrinsic" { #[rustc_nounwind] #[rustc_do_not_const_check] #[inline] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { (ptr == other) as u8 } @@ -2736,7 +2736,7 @@ pub const fn ub_checks() -> bool { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[rustc_intrinsic] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 { // const eval overrides this function, but runtime code for now just returns null pointers. // See <https://github.com/rust-lang/rust/issues/93935>. @@ -2757,7 +2757,7 @@ pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[rustc_intrinsic] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { // Runtime NOP } diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index effd7f6d5435f..d94485a42a85a 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -43,18 +43,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") } - let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); + let intrinsic_fallback_is_spec = Symbol::intern("intrinsic_fallback_is_spec"); if this .tcx .get_attrs_by_path( instance.def_id(), - &[sym::miri, intrinsic_fallback_checks_ub], + &[sym::miri, intrinsic_fallback_is_spec], ) .next() .is_none() { throw_unsup_format!( - "miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that" + "Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that" ); } Ok(Some(ty::Instance { diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr deleted file mode 100644 index 699dda52096f3..0000000000000 --- a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unsupported operation: miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that - --> $DIR/intrinsic_fallback_checks_ub.rs:LL:CC - | -LL | ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that - | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support - = note: BACKTRACE: - = note: inside `main` at $DIR/intrinsic_fallback_checks_ub.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs similarity index 75% rename from src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs rename to src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs index 93c9d3d7814ca..888c548e49b5b 100644 --- a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs @@ -10,5 +10,5 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { fn main() { ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null()); - //~^ ERROR: can only use intrinsic fallback bodies that check UB. + //~^ ERROR: can only use intrinsic fallback bodies that exactly reflect the specification } diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr new file mode 100644 index 0000000000000..db3941a32a56a --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that + --> $DIR/intrinsic_fallback_is_spec.rs:LL:CC + | +LL | ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/intrinsic_fallback_is_spec.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 7faa879486f6aa2871634b54cef3f886591ef323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev> Date: Sat, 11 May 2024 15:40:34 +0200 Subject: [PATCH 3/9] Pattern types: Prohibit generic args on const params --- compiler/rustc_hir_analysis/messages.ftl | 6 +-- .../src/hir_ty_lowering/errors.rs | 12 +++--- .../src/hir_ty_lowering/mod.rs | 11 ++++-- .../bad_const_generics_args_on_const_param.rs | 10 +++++ ..._const_generics_args_on_const_param.stderr | 38 +++++++++++++++++++ tests/ui/type/pattern_types/bad_pat.stderr | 2 +- 6 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs create mode 100644 tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 3edea0191faf1..cf492a2a3fee3 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -371,9 +371,9 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function .suggestion = cast the value to `{$cast_ty}` .help = cast the value to `{$cast_ty}` -hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end" -hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types" - .label = "this type is the same as the inner type without a pattern" +hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end +hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types + .label = this type is the same as the inner type without a pattern hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 8e64a9425bb9f..a8153c4a08819 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1388,7 +1388,7 @@ pub enum GenericsArgsErrExtend<'tcx> { span: Span, }, SelfTyParam(Span), - TyParam(DefId), + Param(DefId), DefVariant, None, } @@ -1504,11 +1504,11 @@ fn generics_args_err_extend<'a>( GenericsArgsErrExtend::DefVariant => { err.note("enum variants can't have type parameters"); } - GenericsArgsErrExtend::TyParam(def_id) => { - if let Some(span) = tcx.def_ident_span(def_id) { - let name = tcx.item_name(def_id); - err.span_note(span, format!("type parameter `{name}` defined here")); - } + GenericsArgsErrExtend::Param(def_id) => { + let span = tcx.def_ident_span(def_id).unwrap(); + let kind = tcx.def_descr(def_id); + let name = tcx.item_name(def_id); + err.span_note(span, format!("{kind} `{name}` defined here")); } GenericsArgsErrExtend::SelfTyParam(span) => { err.span_suggestion_verbose( 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 f7213442ac2dd..37c6ef84f2466 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1756,7 +1756,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assert_eq!(opt_self_ty, None); let _ = self.prohibit_generic_args( path.segments.iter(), - GenericsArgsErrExtend::TyParam(def_id), + GenericsArgsErrExtend::Param(def_id), ); self.lower_ty_param(hir_id) } @@ -2196,10 +2196,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::ExprKind::Path(hir::QPath::Resolved( _, - &hir::Path { - res: Res::Def(DefKind::ConstParam, def_id), .. + path @ &hir::Path { + res: Res::Def(DefKind::ConstParam, def_id), + .. }, )) => { + let _ = self.prohibit_generic_args( + path.segments.iter(), + GenericsArgsErrExtend::Param(def_id), + ); let ty = tcx .type_of(def_id) .no_bound_vars() diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs new file mode 100644 index 0000000000000..050b7b44b4e0d --- /dev/null +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -0,0 +1,10 @@ +#![feature(pattern_types, core_pattern_type)] +#![allow(internal_features)] + +type Pat<const START: u32, const END: u32> = + std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); +//~^ ERROR type and const arguments are not allowed on const parameter `START` +//~| ERROR type arguments are not allowed on const parameter `END` +//~| ERROR associated type bindings are not allowed here + +fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr new file mode 100644 index 0000000000000..40effe924da81 --- /dev/null +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -0,0 +1,38 @@ +error[E0109]: type and const arguments are not allowed on const parameter `START` + --> $DIR/bad_const_generics_args_on_const_param.rs:5:44 + | +LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); + | ----- ^^ ^^^ ^ type and const arguments not allowed + | | + | not allowed on const parameter `START` + | +note: const parameter `START` defined here + --> $DIR/bad_const_generics_args_on_const_param.rs:4:16 + | +LL | type Pat<const START: u32, const END: u32> = + | ^^^^^ + +error[E0109]: type arguments are not allowed on const parameter `END` + --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 + | +LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); + | --- ^ type argument not allowed + | | + | not allowed on const parameter `END` + | +note: const parameter `END` defined here + --> $DIR/bad_const_generics_args_on_const_param.rs:4:34 + | +LL | type Pat<const START: u32, const END: u32> = + | ^^^ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/bad_const_generics_args_on_const_param.rs:5:67 + | +LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); + | ^^^^^^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0109, E0229. +For more information about an error, try `rustc --explain E0109`. diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index 4f0f0bc974276..2abf27100c1de 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -14,7 +14,7 @@ LL | type Positive2 = pattern_type!(i32 is 0..=); | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: "wildcard patterns are not permitted for pattern types" +error: wildcard patterns are not permitted for pattern types --> $DIR/bad_pat.rs:11:33 | LL | type Wild = pattern_type!(() is _); From 7c76eec30ff6cdb00b234896f6e0c5b76ef7143f Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 12 May 2024 09:59:08 +0200 Subject: [PATCH 4/9] reference type safety invariant docs: clarification --- library/core/src/primitive_docs.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index d8597369b9bfd..50e0afab9e6cf 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1475,14 +1475,17 @@ mod prim_usize {} /// /// For instance, this means that unsafe code in a safe function may assume these invariants are /// ensured of arguments passed by the caller, and it may assume that these invariants are ensured -/// of return values from any safe functions it calls. In most cases, the inverse is also true: -/// unsafe code must not violate these invariants when passing arguments to safe functions or -/// returning values from safe functions; such violations may result in undefined behavior. Where -/// exceptions to this latter requirement exist, they will be called out explicitly in documentation. +/// of return values from any safe functions it calls. +/// +/// For the other direction, things are more complicated: when unsafe code passes arguments +/// to safe functions or returns values from safe functions, they generally must *at least* +/// not violate these invariants. The full requirements are stronger, as the reference generally +/// must point to data that is safe to use at type `T`. /// /// It is not decided yet whether unsafe code may violate these invariants temporarily on internal /// data. As a consequence, unsafe code which violates these invariants temporarily on internal data -/// may become unsound in future versions of Rust depending on how this question is decided. +/// may be unsound or become unsound in future versions of Rust depending on how this question is +/// decided. /// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] From 2e97dae8d468623474d05dd84c270583ec3ed374 Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Sat, 18 May 2024 12:40:36 -0400 Subject: [PATCH 5/9] An async closure may implement FnMut/Fn if it has no self-borrows --- compiler/rustc_middle/src/ty/sty.rs | 39 +++++++++++++++++++ .../src/solve/assembly/structural_traits.rs | 13 +++---- .../src/traits/select/candidate_assembly.rs | 15 ++----- .../async-closures/implements-fnmut.rs | 23 +++++++++++ 4 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 tests/ui/async-await/async-closures/implements-fnmut.rs diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9dbcd938e6eda..6526bed5bdd63 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -401,6 +401,45 @@ impl<'tcx> CoroutineClosureArgs<'tcx> { pub fn coroutine_witness_ty(self) -> Ty<'tcx> { self.split().coroutine_witness_ty } + + pub fn has_self_borrows(&self) -> bool { + match self.coroutine_captures_by_ref_ty().kind() { + ty::FnPtr(sig) => sig + .skip_binder() + .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST }) + .is_break(), + ty::Error(_) => true, + _ => bug!(), + } + } +} +/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will +/// detect only regions bound *at* the debruijn index. +struct HasRegionsBoundAt { + binder: ty::DebruijnIndex, +} +// FIXME: Could be optimized to not walk into components with no escaping bound vars. +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt { + type Result = ControlFlow<()>; + fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( + &mut self, + t: &ty::Binder<'tcx, T>, + ) -> Self::Result { + self.binder.shift_in(1); + t.super_visit_with(self)?; + self.binder.shift_out(1); + ControlFlow::Continue(()) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if let ty::ReBound(binder, _) = *r + && self.binder == binder + { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 90cc33e0275b6..f5e397f12d2da 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -300,14 +300,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( return Err(NoSolution); } - // If `Fn`/`FnMut`, we only implement this goal if we - // have no captures. - let no_borrows = match args.tupled_upvars_ty().kind() { - ty::Tuple(tys) => tys.is_empty(), - ty::Error(_) => false, - _ => bug!("tuple_fields called on non-tuple"), - }; - if closure_kind != ty::ClosureKind::FnOnce && !no_borrows { + // A coroutine-closure implements `FnOnce` *always*, since it may + // always be called once. It additionally implements `Fn`/`FnMut` + // only if it has no upvars referencing the closure-env lifetime, + // and if the closure kind permits it. + if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b9e853a067874..fd7c47ad6fb3d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -418,20 +418,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Ambiguity if upvars haven't been constrained yet && !args.tupled_upvars_ty().is_ty_var() { - let no_borrows = match args.tupled_upvars_ty().kind() { - ty::Tuple(tys) => tys.is_empty(), - ty::Error(_) => false, - _ => bug!("tuple_fields called on non-tuple"), - }; // A coroutine-closure implements `FnOnce` *always*, since it may // always be called once. It additionally implements `Fn`/`FnMut` - // only if it has no upvars (therefore no borrows from the closure - // that would need to be represented with a lifetime) and if the - // closure kind permits it. - // FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut` - // if it takes all of its upvars by copy, and none by ref. This would - // require us to record a bit more information during upvar analysis. - if no_borrows && closure_kind.extends(kind) { + // only if it has no upvars referencing the closure-env lifetime, + // and if the closure kind permits it. + if closure_kind.extends(kind) && !args.has_self_borrows() { candidates.vec.push(ClosureCandidate { is_const }); } else if kind == ty::ClosureKind::FnOnce { candidates.vec.push(ClosureCandidate { is_const }); diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs new file mode 100644 index 0000000000000..1ed326cd0618b --- /dev/null +++ b/tests/ui/async-await/async-closures/implements-fnmut.rs @@ -0,0 +1,23 @@ +//@ check-pass +//@ edition: 2021 + +// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!) +// if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env, +// since it's fine to reborrow it with its original lifetime. See the doc comment on +// `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we +// must borrow from the closure env. + +#![feature(async_closure)] + +fn main() {} + +fn needs_fn_mut<T>(x: impl FnMut() -> T) {} + +fn hello(x: &Ty) { + needs_fn_mut(async || { x.hello(); }); +} + +struct Ty; +impl Ty { + fn hello(&self) {} +} From 6b3058204a91bb21e2aa845fedfab85a68f75b94 Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Sun, 19 May 2024 23:45:25 -0400 Subject: [PATCH 6/9] Force the inner coroutine of an async closure to `move` if the outer closure is `move` and `FnOnce` --- compiler/rustc_hir_typeck/src/upvar.rs | 89 ++++++++++++------- .../force-move-due-to-actually-fnonce.rs | 27 ++++++ .../force-move-due-to-inferred-kind.rs | 24 +++++ 3 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs create mode 100644 tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 9d16f0d48159e..e29a410e2e543 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -204,6 +204,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fake_reads: Default::default(), }; + let _ = euv::ExprUseVisitor::new( + &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id), + &mut delegate, + ) + .consume_body(body); + + // There are several curious situations with coroutine-closures where + // analysis is too aggressive with borrows when the coroutine-closure is + // marked `move`. Specifically: + // + // 1. If the coroutine-closure was inferred to be `FnOnce` during signature + // inference, then it's still possible that we try to borrow upvars from + // the coroutine-closure because they are not used by the coroutine body + // in a way that forces a move. See the test: + // `async-await/async-closures/force-move-due-to-inferred-kind.rs`. + // + // 2. If the coroutine-closure is forced to be `FnOnce` due to the way it + // uses its upvars, but not *all* upvars would force the closure to `FnOnce`. + // See the test: `async-await/async-closures/force-move-due-to-actually-fnonce.rs`. + // + // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` + // coroutine bodies can't borrow from their parent closure. To fix this, + // we force the inner coroutine to also be `move`. This only matters for + // coroutine-closures that are `move` since otherwise they themselves will + // be borrowing from the outer environment, so there's no self-borrows occuring. + // + // One *important* note is that we do a call to `process_collected_capture_information` + // to eagerly test whether the coroutine would end up `FnOnce`, but we do this + // *before* capturing all the closure args by-value below, since that would always + // cause the analysis to return `FnOnce`. + if let UpvarArgs::Coroutine(..) = args + && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = + self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") + && let parent_hir_id = + self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id)) + && let parent_ty = self.node_ty(parent_hir_id) + && let hir::CaptureBy::Value { move_kw } = + self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause + { + // (1.) Closure signature inference forced this closure to `FnOnce`. + if let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty) { + capture_clause = hir::CaptureBy::Value { move_kw }; + } + // (2.) The way that the closure uses its upvars means it's `FnOnce`. + else if let (_, ty::ClosureKind::FnOnce, _) = self + .process_collected_capture_information( + capture_clause, + &delegate.capture_information, + ) + { + capture_clause = hir::CaptureBy::Value { move_kw }; + } + } + // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode // to `ByRef` for the `async {}` block internal to async fns/closure. This means // that we would *not* be moving all of the parameters into the async block by default. @@ -253,34 +307,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let _ = euv::ExprUseVisitor::new( - &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id), - &mut delegate, - ) - .consume_body(body); - - // If a coroutine is comes from a coroutine-closure that is `move`, but - // the coroutine-closure was inferred to be `FnOnce` during signature - // inference, then it's still possible that we try to borrow upvars from - // the coroutine-closure because they are not used by the coroutine body - // in a way that forces a move. - // - // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` - // coroutine bodies can't borrow from their parent closure. To fix this, - // we force the inner coroutine to also be `move`. This only matters for - // coroutine-closures that are `move` since otherwise they themselves will - // be borrowing from the outer environment, so there's no self-borrows occuring. - if let UpvarArgs::Coroutine(..) = args - && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = - self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") - && let parent_hir_id = - self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id)) - && let parent_ty = self.node_ty(parent_hir_id) - && let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty) - { - capture_clause = self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause; - } - debug!( "For closure={:?}, capture_information={:#?}", closure_def_id, delegate.capture_information @@ -289,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span); let (capture_information, closure_kind, origin) = self - .process_collected_capture_information(capture_clause, delegate.capture_information); + .process_collected_capture_information(capture_clause, &delegate.capture_information); self.compute_min_captures(closure_def_id, capture_information, span); @@ -545,13 +571,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn process_collected_capture_information( &self, capture_clause: hir::CaptureBy, - capture_information: InferredCaptureInformation<'tcx>, + capture_information: &InferredCaptureInformation<'tcx>, ) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) { let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM; let mut origin: Option<(Span, Place<'tcx>)> = None; let processed = capture_information - .into_iter() + .iter() + .cloned() .map(|(place, mut capture_info)| { // Apply rules for safety before inferring closure kind let (place, capture_kind) = diff --git a/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs new file mode 100644 index 0000000000000..ce49f55e3e304 --- /dev/null +++ b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs @@ -0,0 +1,27 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ check-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn consume(_: String) {} + +fn main() { + block_on::block_on(async { + let x = 1i32; + let s = String::new(); + // `consume(s)` pulls the closure's kind down to `FnOnce`, + // which means that we don't treat the borrow of `x` as a + // self-borrow (with `'env` lifetime). This leads to a lifetime + // error which is solved by forcing the inner coroutine to + // be `move` as well, so that it moves `x`. + let c = async move || { + println!("{x}"); + // This makes the closure FnOnce... + consume(s); + }; + c().await; + }); +} diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs new file mode 100644 index 0000000000000..803c990ef93f1 --- /dev/null +++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs @@ -0,0 +1,24 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ check-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn force_fnonce<T: async FnOnce()>(t: T) -> T { t } + +fn main() { + block_on::block_on(async { + let x = 1i32; + // `force_fnonce` pulls the closure's kind down to `FnOnce`, + // which means that we don't treat the borrow of `x` as a + // self-borrow (with `'env` lifetime). This leads to a lifetime + // error which is solved by forcing the inner coroutine to + // be `move` as well, so that it moves `x`. + let c = force_fnonce(async move || { + println!("{x}"); + }); + c().await; + }); +} From ee4a51a60f4af9c88fa1d74f2eb5e94e599edfaa Mon Sep 17 00:00:00 2001 From: lcnr <rust@lcnr.de> Date: Tue, 21 May 2024 18:01:16 +0000 Subject: [PATCH 7/9] remove tracing tree indent lines --- compiler/rustc_log/src/lib.rs | 1 - compiler/rustc_pattern_analysis/tests/common/mod.rs | 1 - src/librustdoc/lib.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 81257f9be8823..7327db97112f1 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -103,7 +103,6 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { let mut layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_verbose_exit(verbose_entry_exit) diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index e72fddb9e9a81..6e8bb50500554 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -13,7 +13,6 @@ pub fn init_tracing() { use tracing_subscriber::Layer; let _ = tracing_tree::HierarchicalLayer::default() .with_writer(std::io::stderr) - .with_indent_lines(true) .with_ansi(true) .with_targets(true) .with_indent_amount(2) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0650afb90c7ea..7f156d32655b7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -201,7 +201,6 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); let layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_wraparound(10) From ec9571af43d2750eb64c78392653302511d3a9d7 Mon Sep 17 00:00:00 2001 From: lcnr <rust@lcnr.de> Date: Tue, 21 May 2024 18:16:33 +0000 Subject: [PATCH 8/9] update UI tests --- .../occurs-check/associated-type.next.stderr | 8 ++++---- .../occurs-check/associated-type.old.stderr | 16 ++++++++-------- .../structually-relate-aliases.stderr | 4 ++-- ...itrary-self-from-method-substs.default.stderr | 2 +- .../next-solver/issue-118950-root-region.stderr | 8 ++++---- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 7443459b83007..d809a6948f3ea 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,7 +1,7 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 38a02c906d4fc..329086ab7dfdf 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,11 +1,11 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 59fab52b221e2..2f1dfd19c483b 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,5 +1,5 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index bd0519f66c0de..6fff086a89c2e 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -9,7 +9,7 @@ LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? + ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 2e0566cad08e2..17da1f5247963 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -25,10 +25,10 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } error[E0119]: conflicting implementations of trait `Overlap<fn(_)>` for type `fn(_)` --> $DIR/issue-118950-root-region.rs:19:1 | From 1005cc70ae15016b7747bdc5d9e9e0898c8b2084 Mon Sep 17 00:00:00 2001 From: lcnr <rust@lcnr.de> Date: Tue, 21 May 2024 18:16:47 +0000 Subject: [PATCH 9/9] add logging to search graph --- compiler/rustc_trait_selection/src/solve/search_graph.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index bcd210f789bfe..b39ba4c4ac7ce 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -279,6 +279,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> { }; if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) { + debug!("global cache hit"); return result; } @@ -360,7 +361,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> { for _ in 0..FIXPOINT_STEP_LIMIT { match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) { StepResult::Done(final_entry, result) => return (final_entry, result), - StepResult::HasChanged => {} + StepResult::HasChanged => debug!("fixpoint changed provisional results"), } }