From a02a982ffc73457caa1849b09da63e84f78541c6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Jan 2025 21:27:06 +0000 Subject: [PATCH 1/4] Make DeeplyNormalize a real type op --- .../src/type_check/constraint_conversion.rs | 21 +------ .../src/type_check/free_region_relations.rs | 21 ++----- compiler/rustc_middle/src/traits/query.rs | 7 +++ .../src/traits/query/type_op/normalize.rs | 58 ++++++++++++++++++- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 4b7f53213886e..3b48ca305c45b 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -4,15 +4,12 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; +use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::traits::ObligationCause; -use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; -use rustc_trait_selection::traits::ScrubbedTraitError; -use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use tracing::{debug, instrument}; @@ -270,20 +267,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ConstraintCategory<'tcx>, )>, ) -> Ty<'tcx> { - let result = CustomTypeOp::new( - |ocx| { - ocx.deeply_normalize( - &ObligationCause::dummy_with_span(self.span), - self.param_env, - ty, - ) - .map_err(|_: Vec>| NoSolution) - }, - "normalize type outlives obligation", - ) - .fully_perform(self.infcx, self.span); - - match result { + match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span) + { Ok(TypeOpOutput { output: ty, constraints, .. }) => { if let Some(QueryRegionConstraints { outlives }) = constraints { next_outlives_predicates.extend(outlives.iter().copied()); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index edf612f4e97a4..2bac084c9643e 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -5,14 +5,11 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::{InferCtxt, outlives}; -use rustc_infer::traits::ScrubbedTraitError; +use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, Span}; -use rustc_trait_selection::solve::NoSolution; -use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use tracing::{debug, instrument}; use type_op::TypeOpOutput; @@ -360,18 +357,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { output: normalized_outlives, constraints: constraints_normalize, error_info: _, - }) = CustomTypeOp::new( - |ocx| { - ocx.deeply_normalize( - &ObligationCause::dummy_with_span(span), - self.param_env, - outlives, - ) - .map_err(|_: Vec>| NoSolution) - }, - "normalize type outlives obligation", - ) - .fully_perform(self.infcx, span) + }) = self + .param_env + .and(DeeplyNormalize { value: outlives }) + .fully_perform(self.infcx, span) else { self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}")); return; diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 8cd04a6f5e406..5b19d1742cd42 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -41,11 +41,18 @@ pub mod type_op { pub predicate: Predicate<'tcx>, } + /// Normalizes, but not in the new solver. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct Normalize { pub value: T, } + /// Normalizes, and deeply normalizes in the new solver. + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] + pub struct DeeplyNormalize { + pub value: T, + } + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index e8c2528aa6eeb..2f6bbd7f4cf48 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; -pub use rustc_middle::traits::query::type_op::Normalize; +pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; @@ -27,13 +27,54 @@ where T::type_op_method(tcx, canonicalized) } + fn perform_locally_with_next_solver( + _ocx: &ObligationCtxt<'_, 'tcx>, + key: ParamEnvAnd<'tcx, Self>, + _span: Span, + ) -> Result { + Ok(key.value.value) + } +} + +impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize +where + T: Normalizable<'tcx> + 'tcx, +{ + type QueryResponse = T; + + fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option { + if !key.value.value.has_aliases() { Some(key.value.value) } else { None } + } + + fn perform_query( + tcx: TyCtxt<'tcx>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>, + ) -> Result, NoSolution> { + T::type_op_method( + tcx, + CanonicalQueryInput { + typing_mode: canonicalized.typing_mode, + canonical: canonicalized.canonical.unchecked_map( + |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd { + param_env, + value: Normalize { value: value.value }, + }, + ), + }, + ) + } + fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, span: Span, ) -> Result { - // FIXME(-Znext-solver): shouldn't be using old normalizer - Ok(ocx.normalize(&ObligationCause::dummy_with_span(span), key.param_env, key.value.value)) + ocx.deeply_normalize( + &ObligationCause::dummy_with_span(span), + key.param_env, + key.value.value, + ) + .map_err(|_| NoSolution) } } @@ -81,3 +122,14 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { tcx.type_op_normalize_fn_sig(canonicalized) } } + +/// This impl is not needed, since we never normalize type outlives predicates +/// in the old solver, but is required by trait bounds to be happy. +impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> { + fn type_op_method( + _tcx: TyCtxt<'tcx>, + _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + ) -> Result, NoSolution> { + unreachable!("we never normalize PolyTypeOutlivesPredicate") + } +} From ce0c952e968777004fc59f45653be2fda116fee1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Jan 2025 21:39:59 +0000 Subject: [PATCH 2/4] Deeply normalize args for implied bounds --- .../src/type_check/free_region_relations.rs | 2 +- .../implied-bound-from-normalized-arg.rs | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/ui/borrowck/implied-bound-from-normalized-arg.rs diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 2bac084c9643e..a7f8d9c288489 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -264,7 +264,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = param_env - .and(type_op::normalize::Normalize { value: ty }) + .and(DeeplyNormalize { value: ty }) .fully_perform(self.infcx, span) .unwrap_or_else(|guar| TypeOpOutput { output: Ty::new_error(self.infcx.tcx, guar), diff --git a/tests/ui/borrowck/implied-bound-from-normalized-arg.rs b/tests/ui/borrowck/implied-bound-from-normalized-arg.rs new file mode 100644 index 0000000000000..4e9a4953c6b7e --- /dev/null +++ b/tests/ui/borrowck/implied-bound-from-normalized-arg.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Make sure that we can normalize `>::Assoc` to `&'a T` and get +// its implied bounds. + +trait Ref<'a> { + type Assoc; +} +impl<'a, T> Ref<'a> for T where T: 'a { + type Assoc = &'a T; +} + +fn outlives<'a, T: 'a>() {} + +fn test<'a, T>(_: >::Assoc) { + outlives::<'a, T>(); +} + +fn main() {} From ef9d992a0d8a7a093a398e51b42dbea8eed72847 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Jan 2025 21:42:29 +0000 Subject: [PATCH 3/4] Deeply normalize in impl header --- .../src/type_check/free_region_relations.rs | 2 +- .../implied-bound-from-impl-header.rs | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ui/borrowck/implied-bound-from-impl-header.rs diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index a7f8d9c288489..b8008f18a399d 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -301,7 +301,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) { for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { let result: Result<_, ErrorGuaranteed> = param_env - .and(type_op::normalize::Normalize { value: ty }) + .and(DeeplyNormalize { value: ty }) .fully_perform(self.infcx, span); let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else { continue; diff --git a/tests/ui/borrowck/implied-bound-from-impl-header.rs b/tests/ui/borrowck/implied-bound-from-impl-header.rs new file mode 100644 index 0000000000000..326a62b22f055 --- /dev/null +++ b/tests/ui/borrowck/implied-bound-from-impl-header.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Make sure that we can normalize `>::Assoc` to `&'a T` and get +// its implied bounds in impl header. + +trait Ref<'a> { + type Assoc; +} +impl<'a, T> Ref<'a> for T where T: 'a { + type Assoc = &'a T; +} + +fn outlives<'a, T: 'a>() {} + +trait Trait<'a, T> { + fn test(); +} + +impl<'a, T> Trait<'a, T> for >::Assoc { + fn test() { + outlives::<'a, T>(); + } +} + +fn main() {} From d5be3bae5182ad064bf2b28a7c9d6847e08d8463 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Jan 2025 22:22:53 +0000 Subject: [PATCH 4/4] Deeply normalize signature in new solver --- .../src/diagnostics/bound_region_errors.rs | 59 ++++++++++++++++++- .../src/type_check/canonical.rs | 12 ++++ .../src/type_check/free_region_relations.rs | 5 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_middle/src/traits/query.rs | 3 + ...heck-normalized-sig-for-wf.current.stderr} | 6 +- .../check-normalized-sig-for-wf.next.stderr | 47 +++++++++++++++ tests/ui/nll/check-normalized-sig-for-wf.rs | 4 ++ 8 files changed, 129 insertions(+), 9 deletions(-) rename tests/ui/nll/{check-normalized-sig-for-wf.stderr => check-normalized-sig-for-wf.current.stderr} (90%) create mode 100644 tests/ui/nll/check-normalized-sig-for-wf.next.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 30b0a35858028..aa968a1e40f3e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -9,8 +9,8 @@ use rustc_infer::infer::{ }; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::query::{ - CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal, - CanonicalTypeOpProvePredicateGoal, + CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal, + CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ @@ -109,6 +109,14 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable> + 'tcx> ToUnivers } } +impl<'tcx, T: Copy + fmt::Display + TypeFoldable> + 'tcx> ToUniverseInfo<'tcx> + for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> +{ + fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe })) + } +} + impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe })) @@ -285,6 +293,53 @@ where } } +struct DeeplyNormalizeQuery<'tcx, T> { + canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>, + base_universe: ty::UniverseIndex, +} + +impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T> +where + T: Copy + fmt::Display + TypeFoldable> + 'tcx, +{ + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> { + tcx.dcx().create_err(HigherRankedLifetimeError { + cause: Some(HigherRankedErrorCause::CouldNotNormalize { + value: self.canonical_query.canonical.value.value.value.to_string(), + }), + span, + }) + } + + fn base_universe(&self) -> ty::UniverseIndex { + self.base_universe + } + + fn nice_error<'infcx>( + &self, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, + cause: ObligationCause<'tcx>, + placeholder_region: ty::Region<'tcx>, + error_region: Option>, + ) -> Option> { + let (infcx, key, _) = + mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); + let ocx = ObligationCtxt::new(&infcx); + + let (param_env, value) = key.into_parts(); + let _ = ocx.deeply_normalize(&cause, param_env, value.value); + + let diag = try_extract_error_from_fulfill_cx( + &ocx, + mbcx.mir_def_id(), + placeholder_region, + error_region, + )? + .with_dcx(mbcx.dcx()); + Some(diag) + } +} + struct AscribeUserTypeQuery<'tcx> { canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>, base_universe: ty::UniverseIndex, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index bffd9f383343d..b3fa786a5177c 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.normalize_with_category(value, location, ConstraintCategory::Boring) } + pub(super) fn deeply_normalize(&mut self, value: T, location: impl NormalizeLocation) -> T + where + T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, + { + let result: Result<_, ErrorGuaranteed> = self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }), + ); + result.unwrap_or(value) + } + #[instrument(skip(self), level = "debug")] pub(super) fn normalize_with_category( &mut self, diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index b8008f18a399d..efbae1e153537 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -300,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // Add implied bounds from impl header. if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) { for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { - let result: Result<_, ErrorGuaranteed> = param_env - .and(DeeplyNormalize { value: ty }) - .fully_perform(self.infcx, span); + let result: Result<_, ErrorGuaranteed> = + param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span); let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else { continue; }; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 26a5d438edb98..93081919ec79d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1116,7 +1116,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring, ); - let sig = self.normalize(unnormalized_sig, term_location); + let sig = self.deeply_normalize(unnormalized_sig, term_location); // HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))` // with built-in `Fn` implementations, since the impl may not be // well-formed itself. diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 5b19d1742cd42..4203c8fd86149 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -87,6 +87,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize>>; +pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> = + CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize>>; + pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>; diff --git a/tests/ui/nll/check-normalized-sig-for-wf.stderr b/tests/ui/nll/check-normalized-sig-for-wf.current.stderr similarity index 90% rename from tests/ui/nll/check-normalized-sig-for-wf.stderr rename to tests/ui/nll/check-normalized-sig-for-wf.current.stderr index 5c96b0c6561a1..b25ae72f7fb9a 100644 --- a/tests/ui/nll/check-normalized-sig-for-wf.stderr +++ b/tests/ui/nll/check-normalized-sig-for-wf.current.stderr @@ -1,5 +1,5 @@ error[E0597]: `s` does not live long enough - --> $DIR/check-normalized-sig-for-wf.rs:7:7 + --> $DIR/check-normalized-sig-for-wf.rs:11:7 | LL | s: String, | - binding `s` declared here @@ -14,7 +14,7 @@ LL | } | - `s` dropped here while still borrowed error[E0521]: borrowed data escapes outside of function - --> $DIR/check-normalized-sig-for-wf.rs:15:5 + --> $DIR/check-normalized-sig-for-wf.rs:19:5 | LL | fn extend(input: &T) -> &'static T { | ----- - let's call the lifetime of this reference `'1` @@ -28,7 +28,7 @@ LL | n(input).0 | argument requires that `'1` must outlive `'static` error[E0521]: borrowed data escapes outside of function - --> $DIR/check-normalized-sig-for-wf.rs:23:5 + --> $DIR/check-normalized-sig-for-wf.rs:27:5 | LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { | -- ----- `input` is a reference that is only valid in the function body diff --git a/tests/ui/nll/check-normalized-sig-for-wf.next.stderr b/tests/ui/nll/check-normalized-sig-for-wf.next.stderr new file mode 100644 index 0000000000000..b25ae72f7fb9a --- /dev/null +++ b/tests/ui/nll/check-normalized-sig-for-wf.next.stderr @@ -0,0 +1,47 @@ +error[E0597]: `s` does not live long enough + --> $DIR/check-normalized-sig-for-wf.rs:11:7 + | +LL | s: String, + | - binding `s` declared here +... +LL | f(&s).0 + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed + +error[E0521]: borrowed data escapes outside of function + --> $DIR/check-normalized-sig-for-wf.rs:19:5 + | +LL | fn extend(input: &T) -> &'static T { + | ----- - let's call the lifetime of this reference `'1` + | | + | `input` is a reference that is only valid in the function body +... +LL | n(input).0 + | ^^^^^^^^ + | | + | `input` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/check-normalized-sig-for-wf.rs:27:5 + | +LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { + | -- ----- `input` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | n(input).0 + | ^^^^^^^^ + | | + | `input` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/check-normalized-sig-for-wf.rs b/tests/ui/nll/check-normalized-sig-for-wf.rs index cb0f34ce02f7a..9d7411fd8124a 100644 --- a/tests/ui/nll/check-normalized-sig-for-wf.rs +++ b/tests/ui/nll/check-normalized-sig-for-wf.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + // fn whoops( s: String,