diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 868c6f11b68dc..e112f0eaf2a62 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { let assumptions = elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied()); - for &(constraint, constraint_category) in constraints { + for &(constraint, constraint_category, _) in constraints { constraint.iter_outlives().for_each(|predicate| { self.convert(predicate, constraint_category, &assumptions); }); @@ -205,6 +205,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { t1, r2, constraint_category, + ty::VisibleForLeakCheck::Yes, ); } @@ -296,7 +297,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // FIXME(higher_ranked_auto): What should we do with the assumptions here? if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints { next_outlives_predicates.extend(constraints.iter().flat_map( - |(constraint, category)| { + |(constraint, category, _)| { constraint.iter_outlives().map(|outlives| (outlives, *category)) }, )); @@ -315,6 +316,7 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' a: ty::Region<'tcx>, b: ty::Region<'tcx>, constraint_category: ConstraintCategory<'tcx>, + _vis: ty::VisibleForLeakCheck, ) { let b = self.to_region_vid(b); let a = self.to_region_vid(a); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 32610619fe713..6cedd5ca5265c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -709,6 +709,7 @@ fn ty_known_to_outlive<'tcx>( sub_region: region, sup_type: ty, origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None), + visible_for_leak_check: ty::VisibleForLeakCheck::Yes, }); }) } @@ -728,6 +729,7 @@ fn region_known_to_outlive<'tcx>( SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a, + ty::VisibleForLeakCheck::Yes, ); }) } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index d1ce29b703eea..e60ee006c8019 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -490,7 +490,12 @@ pub(crate) fn coerce_unsized_info<'tcx>( } (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { - infcx.sub_regions(SubregionOrigin::RelateObjectBound(span), r_b, r_a); + infcx.sub_regions( + SubregionOrigin::RelateObjectBound(span), + r_b, + r_a, + ty::VisibleForLeakCheck::Yes, + ); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b }; check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty)) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index a575ba79df45c..3ccd52d487298 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -228,7 +228,8 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { | ty::ReErased | ty::ReStatic | ty::ReError(_) => r, - ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), + ty::ReVar(_) => canonicalizer + .canonical_var_for_region(CanonicalVarKind::Region(ty::UniverseIndex::ROOT), r), ty::RePlaceholder(..) | ty::ReBound(..) => { // We only expect region names that the user can type. bug!("unexpected region in query response: `{:?}`", r) @@ -706,23 +707,26 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { } /// Shorthand helper that creates a canonical region variable for - /// `r` (always in the root universe). The reason that we always - /// put these variables into the root universe is because this - /// method is used during **query construction:** in that case, we - /// are taking all the regions and just putting them into the most - /// generic context we can. This may generate solutions that don't - /// fit (e.g., that equate some region variable with a placeholder - /// it can't name) on the caller side, but that's ok, the caller - /// can figure that out. In the meantime, it maximizes our + /// `r` (always as a placeholder in the root universe). The reason + /// that we always put these variables into the root universe as a + /// placeholder is because this method is used during + /// **query construction:** in that case, we are taking all the + /// free regions and just putting them into the most generic context + /// we can. This makes any region constraints between them, including + /// region equalities, to be preserved and propagated to the caller + /// instead of unifying them. In the meantime, it maximizes our /// caching. - /// - /// (This works because unification never fails -- and hence trait - /// selection is never affected -- due to a universe mismatch.) fn canonical_var_for_region_in_root_universe( &mut self, r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { - self.canonical_var_for_region(CanonicalVarKind::Region(ty::UniverseIndex::ROOT), r) + self.canonical_var_for_region( + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.var_kinds.len().into(), + )), + r, + ) } /// Creates a canonical variable (with the given `info`) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 5203b4ee5d99f..cf84010d28729 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -188,14 +188,14 @@ impl<'tcx> InferCtxt<'tcx> { let InferOk { value: result_args, obligations } = self.query_response_instantiation(cause, param_env, original_values, query_response)?; - for (constraint, _category) in &query_response.value.region_constraints.constraints { + for (constraint, _category, vis) in &query_response.value.region_constraints.constraints { let constraint = instantiate_value(self.tcx, &result_args, *constraint); match constraint { ty::RegionConstraint::Outlives(predicate) => { - self.register_outlives_constraint(predicate, cause); + self.register_outlives_constraint(predicate, *vis, cause); } ty::RegionConstraint::Eq(predicate) => { - self.register_region_eq_constraint(predicate, cause); + self.register_region_eq_constraint(predicate, *vis, cause); } } } @@ -288,6 +288,7 @@ impl<'tcx> InferCtxt<'tcx> { output_query_region_constraints.constraints.push(( ty::RegionEqPredicate(v_o.into(), v_r).into(), constraint_category, + ty::VisibleForLeakCheck::Yes, )); } } @@ -586,6 +587,7 @@ impl<'tcx> InferCtxt<'tcx> { SubregionOrigin::RelateRegionParamBound(cause.span, None), v1, v2, + ty::VisibleForLeakCheck::Yes, ); } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { @@ -623,20 +625,23 @@ pub fn make_query_region_constraints<'tcx>( | ConstraintKind::RegSubReg => { // Swap regions because we are going from sub (<=) to outlives (>=). let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub).into(); - (constraint, origin.to_constraint_category()) + (constraint, origin.to_constraint_category(), c.visible_for_leak_check) } ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => { let constraint = ty::RegionEqPredicate(c.sup, c.sub).into(); - (constraint, origin.to_constraint_category()) + (constraint, origin.to_constraint_category(), c.visible_for_leak_check) } }) - .chain(outlives_obligations.into_iter().map(|obl| { - ( - ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region).into(), - obl.origin.to_constraint_category(), - ) - })) + .chain(outlives_obligations.into_iter().map( + |TypeOutlivesConstraint { sub_region, sup_type, origin, visible_for_leak_check }| { + ( + ty::OutlivesPredicate(sup_type.into(), sub_region).into(), + origin.to_constraint_category(), + visible_for_leak_check, + ) + }, + )) .collect(); QueryRegionConstraints { constraints, assumptions } diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index fada30ff30633..cab5efc4b025a 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -256,24 +256,44 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.probe(|_| probe()) } - fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, span: Span) { + fn sub_regions( + &self, + sub: ty::Region<'tcx>, + sup: ty::Region<'tcx>, + vis: ty::VisibleForLeakCheck, + span: Span, + ) { self.inner.borrow_mut().unwrap_region_constraints().make_subregion( SubregionOrigin::RelateRegionParamBound(span, None), sub, sup, + vis, ); } - fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) { + fn equate_regions( + &self, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, + vis: ty::VisibleForLeakCheck, + span: Span, + ) { self.inner.borrow_mut().unwrap_region_constraints().make_eqregion( SubregionOrigin::RelateRegionParamBound(span, None), a, b, + vis, ); } - fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { - self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span)); + fn register_ty_outlives( + &self, + ty: Ty<'tcx>, + r: ty::Region<'tcx>, + vis: ty::VisibleForLeakCheck, + span: Span, + ) { + self.register_type_outlives_constraint(ty, r, vis, &ObligationCause::dummy_with_span(span)); } type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 26c03066c7e40..dedff9ceddb8c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -510,6 +510,7 @@ pub struct TypeOutlivesConstraint<'tcx> { pub sub_region: ty::Region<'tcx>, pub sup_type: Ty<'tcx>, pub origin: SubregionOrigin<'tcx>, + pub visible_for_leak_check: ty::VisibleForLeakCheck, } /// Used to configure inference contexts before their creation. @@ -698,8 +699,9 @@ impl<'tcx> InferCtxt<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + vis: ty::VisibleForLeakCheck, ) { - self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b); + self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b, vis); } #[instrument(skip(self), level = "debug")] @@ -708,8 +710,9 @@ impl<'tcx> InferCtxt<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + vis: ty::VisibleForLeakCheck, ) { - self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin, a, b); + self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin, a, b, vis); } /// Processes a `Coerce` predicate from the fulfillment context. diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index e98bee3b12cde..eb30d2b795bc1 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -85,14 +85,15 @@ impl<'tcx> InferCtxt<'tcx> { pub fn register_outlives_constraint( &self, ty::OutlivesPredicate(arg, r2): ty::ArgOutlivesPredicate<'tcx>, + vis: ty::VisibleForLeakCheck, cause: &ObligationCause<'tcx>, ) { match arg.kind() { ty::GenericArgKind::Lifetime(r1) => { - self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), cause); + self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), vis, cause); } ty::GenericArgKind::Type(ty1) => { - self.register_type_outlives_constraint(ty1, r2, cause); + self.register_type_outlives_constraint(ty1, r2, vis, cause); } ty::GenericArgKind::Const(_) => unreachable!(), } @@ -101,24 +102,26 @@ impl<'tcx> InferCtxt<'tcx> { pub fn register_region_eq_constraint( &self, ty::RegionEqPredicate(r_a, r_b): ty::RegionEqPredicate<'tcx>, + vis: ty::VisibleForLeakCheck, cause: &ObligationCause<'tcx>, ) { let origin = SubregionOrigin::from_obligation_cause(cause, || { SubregionOrigin::RelateRegionParamBound(cause.span, None) }); - self.equate_regions(origin, r_a, r_b); + self.equate_regions(origin, r_a, r_b, vis); } pub fn register_region_outlives_constraint( &self, ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>, + vis: ty::VisibleForLeakCheck, cause: &ObligationCause<'tcx>, ) { let origin = SubregionOrigin::from_obligation_cause(cause, || { SubregionOrigin::RelateRegionParamBound(cause.span, None) }); // `'a: 'b` ==> `'b <= 'a` - self.sub_regions(origin, r_b, r_a); + self.sub_regions(origin, r_b, r_a, vis); } /// Registers that the given region obligation must be resolved @@ -140,6 +143,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, sup_type: Ty<'tcx>, sub_region: Region<'tcx>, + vis: ty::VisibleForLeakCheck, cause: &ObligationCause<'tcx>, ) { // `is_global` means the type has no params, infer, placeholder, or non-`'static` @@ -172,6 +176,7 @@ impl<'tcx> InferCtxt<'tcx> { sup_type, sub_region, origin, + visible_for_leak_check: vis, }); } @@ -233,7 +238,9 @@ impl<'tcx> InferCtxt<'tcx> { ); } - for TypeOutlivesConstraint { sup_type, sub_region, origin } in my_region_obligations { + for TypeOutlivesConstraint { sup_type, sub_region, origin, visible_for_leak_check } in + my_region_obligations + { let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region)); let ty::OutlivesPredicate(sup_type, sub_region) = deeply_normalize_ty(outlives, origin.clone()) @@ -264,7 +271,13 @@ impl<'tcx> InferCtxt<'tcx> { outlives_env.known_type_outlives(), ); let category = origin.to_constraint_category(); - outlives.type_must_outlive(origin, sup_type, sub_region, category); + outlives.type_must_outlive( + origin, + sup_type, + sub_region, + category, + visible_for_leak_check, + ); } } @@ -296,6 +309,7 @@ pub trait TypeOutlivesDelegate<'tcx> { a: ty::Region<'tcx>, b: ty::Region<'tcx>, constraint_category: ConstraintCategory<'tcx>, + vis: ty::VisibleForLeakCheck, ); fn push_verify( @@ -345,12 +359,13 @@ where ty: Ty<'tcx>, region: ty::Region<'tcx>, category: ConstraintCategory<'tcx>, + vis: ty::VisibleForLeakCheck, ) { assert!(!ty.has_escaping_bound_vars()); let mut components = smallvec![]; push_outlives_components(self.tcx, ty, &mut components); - self.components_must_outlive(origin, &components, region, category); + self.components_must_outlive(origin, &components, region, category, vis); } fn components_must_outlive( @@ -359,12 +374,14 @@ where components: &[Component>], region: ty::Region<'tcx>, category: ConstraintCategory<'tcx>, + vis: ty::VisibleForLeakCheck, ) { for component in components.iter() { let origin = origin.clone(); match component { Component::Region(region1) => { - self.delegate.push_sub_region_constraint(origin, region, *region1, category); + self.delegate + .push_sub_region_constraint(origin, region, *region1, category, vis); } Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); @@ -372,9 +389,11 @@ where Component::Placeholder(placeholder_ty) => { self.placeholder_ty_must_outlive(origin, region, *placeholder_ty); } - Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty), + Component::Alias(alias_ty) => { + self.alias_ty_must_outlive(origin, region, *alias_ty, vis) + } Component::EscapingAlias(subcomponents) => { - self.components_must_outlive(origin, subcomponents, region, category); + self.components_must_outlive(origin, subcomponents, region, category, vis); } Component::UnresolvedInferenceVariable(v) => { // Ignore this, we presume it will yield an error later, @@ -424,6 +443,7 @@ where origin: infer::SubregionOrigin<'tcx>, region: ty::Region<'tcx>, alias_ty: ty::AliasTy<'tcx>, + vis: ty::VisibleForLeakCheck, ) { // An optimization for a common case with opaque types. if alias_ty.args.is_empty() { @@ -486,7 +506,7 @@ where { debug!("no declared bounds"); let opt_variances = self.tcx.opt_alias_variances(kind); - self.args_must_outlive(alias_ty.args, origin, region, opt_variances); + self.args_must_outlive(alias_ty.args, origin, region, opt_variances, vis); return; } @@ -518,7 +538,7 @@ where debug!(?unique_bound); debug!("unique declared bound appears in trait ref"); let category = origin.to_constraint_category(); - self.delegate.push_sub_region_constraint(origin, region, unique_bound, category); + self.delegate.push_sub_region_constraint(origin, region, unique_bound, category, vis); return; } @@ -539,6 +559,7 @@ where origin: infer::SubregionOrigin<'tcx>, region: ty::Region<'tcx>, opt_variances: Option<&[ty::Variance]>, + vis: ty::VisibleForLeakCheck, ) { let constraint = origin.to_constraint_category(); for (index, arg) in args.iter().enumerate() { @@ -555,11 +576,12 @@ where region, lt, constraint, + vis, ); } } GenericArgKind::Type(ty) => { - self.type_must_outlive(origin.clone(), ty, region, constraint); + self.type_must_outlive(origin.clone(), ty, region, constraint, vis); } GenericArgKind::Const(_) => { // Const parameters don't impose constraints. @@ -576,8 +598,9 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> { a: ty::Region<'tcx>, b: ty::Region<'tcx>, _constraint_category: ConstraintCategory<'tcx>, + vis: ty::VisibleForLeakCheck, ) { - self.sub_regions(origin, a, b) + self.sub_regions(origin, a, b, vis) } fn push_verify( diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 81a3ca6755d20..2cbf4332038a9 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -369,7 +369,11 @@ impl<'tcx> MiniGraph<'tcx> { Self::iterate_region_constraints( region_constraints, only_consider_snapshot, - |target, source| { + |target, source, vis| { + if vis == ty::VisibleForLeakCheck::No { + return; + } + let source_node = Self::add_node(&mut nodes, source); let target_node = Self::add_node(&mut nodes, target); edges.push((source_node, target_node)); @@ -384,7 +388,7 @@ impl<'tcx> MiniGraph<'tcx> { fn iterate_region_constraints( region_constraints: &RegionConstraintCollector<'_, 'tcx>, only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, - mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>), + mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>, ty::VisibleForLeakCheck), ) { if let Some(snapshot) = only_consider_snapshot { for undo_entry in @@ -392,10 +396,11 @@ impl<'tcx> MiniGraph<'tcx> { { match undo_entry { &AddConstraint(i) => { - region_constraints.data().constraints[i] - .0 - .iter_outlives() - .for_each(|c| each_edge(c.sub, c.sup)); + region_constraints.data().constraints[i].0.iter_outlives().for_each( + |Constraint { kind: _, sub, sup, visible_for_leak_check }| { + each_edge(sub, sup, visible_for_leak_check) + }, + ); } &AddVerify(i) => span_bug!( region_constraints.data().verifys[i].origin.span(), @@ -410,7 +415,9 @@ impl<'tcx> MiniGraph<'tcx> { .constraints .iter() .flat_map(|(c, _)| c.iter_outlives()) - .for_each(|c| each_edge(c.sub, c.sup)) + .for_each(|Constraint { kind: _, sub, sup, visible_for_leak_check }| { + each_edge(sub, sup, visible_for_leak_check) + }) } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 38b87eb7a9863..03bcb5215ee1a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -115,10 +115,11 @@ pub enum ConstraintKind { #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub struct Constraint<'tcx> { pub kind: ConstraintKind, - // If `kind` is `VarSubVar` or `VarSubReg`, this must be a `ReVar`. + // If `kind` is `VarSubVar`, `VarSubReg`, `VarEqVar` or `VarEqReg`, this must be a `ReVar`. pub sub: Region<'tcx>, - // If `kind` is `VarSubVar` or `RegSubVar`, this must be a `ReVar`. + // If `kind` is `VarSubVar`, `RegSubVar` or `VarEqVar`, this must be a `ReVar`. pub sup: Region<'tcx>, + pub visible_for_leak_check: ty::VisibleForLeakCheck, } impl Constraint<'_> { @@ -127,7 +128,7 @@ impl Constraint<'_> { } pub fn iter_outlives(self) -> impl Iterator { - let Constraint { kind, sub, sup } = self; + let Constraint { kind, sub, sup, visible_for_leak_check } = self; match kind { ConstraintKind::VarSubVar @@ -135,18 +136,42 @@ impl Constraint<'_> { | ConstraintKind::VarSubReg | ConstraintKind::RegSubReg => iter::once(self).chain(None), - ConstraintKind::VarEqVar => { - iter::once(Constraint { kind: ConstraintKind::VarSubVar, sub, sup }) - .chain(Some(Constraint { kind: ConstraintKind::VarSubVar, sub: sup, sup: sub })) - } - ConstraintKind::VarEqReg => { - iter::once(Constraint { kind: ConstraintKind::VarSubReg, sub, sup }) - .chain(Some(Constraint { kind: ConstraintKind::RegSubVar, sub: sup, sup: sub })) - } - ConstraintKind::RegEqReg => { - iter::once(Constraint { kind: ConstraintKind::RegSubReg, sub, sup }) - .chain(Some(Constraint { kind: ConstraintKind::RegSubReg, sub: sup, sup: sub })) - } + ConstraintKind::VarEqVar => iter::once(Constraint { + kind: ConstraintKind::VarSubVar, + sub, + sup, + visible_for_leak_check, + }) + .chain(Some(Constraint { + kind: ConstraintKind::VarSubVar, + sub: sup, + sup: sub, + visible_for_leak_check, + })), + ConstraintKind::VarEqReg => iter::once(Constraint { + kind: ConstraintKind::VarSubReg, + sub, + sup, + visible_for_leak_check, + }) + .chain(Some(Constraint { + kind: ConstraintKind::RegSubVar, + sub: sup, + sup: sub, + visible_for_leak_check, + })), + ConstraintKind::RegEqReg => iter::once(Constraint { + kind: ConstraintKind::RegSubReg, + sub, + sup, + visible_for_leak_check, + }) + .chain(Some(Constraint { + kind: ConstraintKind::RegSubReg, + sub: sup, + sup: sub, + visible_for_leak_check, + })), } } } @@ -457,6 +482,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { origin: SubregionOrigin<'tcx>, a: Region<'tcx>, b: Region<'tcx>, + visible_for_leak_check: ty::VisibleForLeakCheck, ) { if a != b { // FIXME: We could only emit constraints if `unify_var_{var, value}` fails when @@ -467,7 +493,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } (ReVar(a_vid), ReVar(b_vid), _, _) => { self.add_constraint( - Constraint { kind: ConstraintKind::VarEqVar, sub: a, sup: b }, + Constraint { + kind: ConstraintKind::VarEqVar, + sub: a, + sup: b, + visible_for_leak_check, + }, origin, ); debug!("make_eqregion: unifying {:?} with {:?}", a_vid, b_vid); @@ -479,12 +510,22 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { if reg.is_static() { // all regions are subregions of static, so don't go bidirectional here self.add_constraint( - Constraint { kind: ConstraintKind::RegSubVar, sub: reg, sup: var }, + Constraint { + kind: ConstraintKind::RegSubVar, + sub: reg, + sup: var, + visible_for_leak_check, + }, origin, ); } else { self.add_constraint( - Constraint { kind: ConstraintKind::VarEqReg, sub: var, sup: reg }, + Constraint { + kind: ConstraintKind::VarEqReg, + sub: var, + sup: reg, + visible_for_leak_check, + }, origin, ); } @@ -500,13 +541,23 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { (ReStatic, _, st, reg) | (_, ReStatic, reg, st) => { // all regions are subregions of static, so don't go bidirectional here self.add_constraint( - Constraint { kind: ConstraintKind::RegSubReg, sub: st, sup: reg }, + Constraint { + kind: ConstraintKind::RegSubReg, + sub: st, + sup: reg, + visible_for_leak_check, + }, origin, ); } _ => { self.add_constraint( - Constraint { kind: ConstraintKind::RegEqReg, sub: a, sup: b }, + Constraint { + kind: ConstraintKind::RegEqReg, + sub: a, + sup: b, + visible_for_leak_check, + }, origin, ); } @@ -520,6 +571,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, + visible_for_leak_check: ty::VisibleForLeakCheck, ) { // cannot add constraints once regions are resolved debug!("origin = {:#?}", origin); @@ -534,19 +586,33 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { (ReVar(sub_id), ReVar(sup_id)) => { if sub_id != sup_id { self.add_constraint( - Constraint { kind: ConstraintKind::VarSubVar, sub, sup }, + Constraint { + kind: ConstraintKind::VarSubVar, + sub, + sup, + visible_for_leak_check, + }, origin, ); } } - (_, ReVar(_)) => self - .add_constraint(Constraint { kind: ConstraintKind::RegSubVar, sub, sup }, origin), - (ReVar(_), _) => self - .add_constraint(Constraint { kind: ConstraintKind::VarSubReg, sub, sup }, origin), + (_, ReVar(_)) => self.add_constraint( + Constraint { kind: ConstraintKind::RegSubVar, sub, sup, visible_for_leak_check }, + origin, + ), + (ReVar(_), _) => self.add_constraint( + Constraint { kind: ConstraintKind::VarSubReg, sub, sup, visible_for_leak_check }, + origin, + ), _ => { if sub != sup { self.add_constraint( - Constraint { kind: ConstraintKind::RegSubReg, sub, sup }, + Constraint { + kind: ConstraintKind::RegSubReg, + sub, + sup, + visible_for_leak_check, + }, origin, ) } @@ -655,8 +721,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { let new_r = ty::Region::new_var(tcx, c); for old_r in [a, b] { match t { - Glb => self.make_subregion(origin.clone(), new_r, old_r), - Lub => self.make_subregion(origin.clone(), old_r, new_r), + Glb => { + self.make_subregion(origin.clone(), new_r, old_r, ty::VisibleForLeakCheck::Yes) + } + Lub => { + self.make_subregion(origin.clone(), old_r, new_r, ty::VisibleForLeakCheck::Yes) + } } } debug!("combine_vars() c={:?}", c); diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 408e2a055f1ef..595392fcfb524 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -223,26 +223,29 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { match self.ambient_variance { // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) ty::Covariant => { - self.infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .make_subregion(origin, b, a); + self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion( + origin, + b, + a, + ty::VisibleForLeakCheck::Yes, + ); } // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) ty::Contravariant => { - self.infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .make_subregion(origin, a, b); + self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion( + origin, + a, + b, + ty::VisibleForLeakCheck::Yes, + ); } ty::Invariant => { - self.infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .make_eqregion(origin, a, b); + self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion( + origin, + a, + b, + ty::VisibleForLeakCheck::Yes, + ); } ty::Bivariant => { unreachable!("Expected bivariance to be handled in relate_with_variance") diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 033e3e36b0247..c94acde0355a5 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -135,7 +135,8 @@ impl<'tcx, R> QueryResponse<'tcx, R> { } } -pub type QueryRegionConstraint<'tcx> = (ty::RegionConstraint<'tcx>, ConstraintCategory<'tcx>); +pub type QueryRegionConstraint<'tcx> = + (ty::RegionConstraint<'tcx>, ConstraintCategory<'tcx>, ty::VisibleForLeakCheck); #[derive(Default)] pub struct CanonicalParamEnvCache<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 59cc6a601bfa8..af7820ba2a6cc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -63,7 +63,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt; )] use rustc_type_ir::inherent; pub use rustc_type_ir::relate::VarianceDiagInfo; -pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind}; +pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind, VisibleForLeakCheck}; pub use rustc_type_ir::*; #[allow(hidden_glob_reexports, unused_imports)] use rustc_type_ir::{InferCtxtLike, Interner}; diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 0a3672343e33c..c5a5d2f53596d 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -417,7 +417,10 @@ impl, I: Interner> TypeFolder for Canonicaliz // when checking whether a `ParamEnv` candidate is global. ty::ReStatic => match self.canonicalize_mode { CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { - CanonicalVarKind::Region(ty::UniverseIndex::ROOT) + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) } CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) | CanonicalizeMode::Response { .. } => return r, @@ -431,24 +434,42 @@ impl, I: Interner> TypeFolder for Canonicaliz // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input(_) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => return r, }, ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { - CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input(_) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => { panic!("unexpected region in response: {r:?}") } }, ty::RePlaceholder(placeholder) => match self.canonicalize_mode { - // We canonicalize placeholder regions as existentials in query inputs. - CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input(_) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { max_input_universe } => { // If we have a placeholder region inside of a query, it must be from - // a new universe. - if max_input_universe.can_name(placeholder.universe()) { + // a new universe, unless it's anon from the root universe, which is + // used for canonicalization of any free region from the input. + if !(placeholder.universe() == ty::UniverseIndex::ROOT + && placeholder.bound.kind == ty::BoundRegionKind::Anon) + && max_input_universe.can_name(placeholder.universe()) + { panic!("new placeholder in universe {max_input_universe:?}: {r:?}"); } CanonicalVarKind::PlaceholderRegion(placeholder) @@ -462,7 +483,12 @@ impl, I: Interner> TypeFolder for Canonicaliz "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { - CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input(_) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => { CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) } diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index a32a693a899cf..f5919b1269cf1 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -25,7 +25,7 @@ use crate::delegate::SolverDelegate; use crate::resolve::eager_resolve_vars; use crate::solve::{ CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, Goal, - NestedNormalizationGoals, QueryInput, Response, inspect, + NestedNormalizationGoals, QueryInput, Response, VisibleForLeakCheck, inspect, }; pub mod canonicalizer; @@ -99,6 +99,7 @@ pub(super) fn instantiate_and_apply_query_response( param_env: I::ParamEnv, original_values: &[I::GenericArg], response: CanonicalResponse, + visible_for_leak_check: VisibleForLeakCheck, span: I::Span, ) -> (NestedNormalizationGoals, Certainty) where @@ -116,7 +117,11 @@ where let ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } = &*external_constraints; - register_region_constraints(delegate, region_constraints, span); + register_region_constraints( + delegate, + region_constraints.iter().map(|(c, vis)| (*c, vis.and(visible_for_leak_check))), + span, + ); register_new_opaque_types(delegate, opaque_types, span); (normalization_nested_goals.clone(), certainty) @@ -250,21 +255,21 @@ fn unify_query_var_values( fn register_region_constraints( delegate: &D, - constraints: &[ty::RegionConstraint], + constraints: impl IntoIterator, VisibleForLeakCheck)>, span: I::Span, ) where D: SolverDelegate, I: Interner, { - for &constraint in constraints { + for (constraint, vis) in constraints { match constraint { ty::RegionConstraint::Outlives(ty::OutlivesPredicate(lhs, rhs)) => match lhs.kind() { - ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span), - ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span), + ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, vis, span), + ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, vis, span), ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"), }, ty::RegionConstraint::Eq(ty::RegionEqPredicate(lhs, rhs)) => { - delegate.equate_regions(lhs, rhs, span) + delegate.equate_regions(lhs, rhs, vis, span) } } } diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 7cf4e8a9238a5..541276f5925da 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; +use rustc_type_ir::solve::{Certainty, Goal, NoSolution, VisibleForLeakCheck}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; pub trait SolverDelegate: Deref + Sized { @@ -45,7 +45,9 @@ pub trait SolverDelegate: Deref + Sized { term: ::Term, ) -> Option::Predicate>>>; - fn make_deduplicated_region_constraints(&self) -> Vec>; + fn make_deduplicated_region_constraints( + &self, + ) -> Vec<(ty::RegionConstraint, VisibleForLeakCheck)>; fn instantiate_canonical( &self, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index e224febd3c927..68e973e7243ef 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -30,7 +30,8 @@ use crate::solve::ty::may_use_unstable_feature; use crate::solve::{ CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalSource, GoalStalledOn, HasChanged, MaybeCause, - NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, Response, inspect, + NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, Response, VisibleForLeakCheck, + inspect, }; mod probe; @@ -202,7 +203,7 @@ where stalled_on: Option>, ) -> Result, NoSolution> { EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| { - ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on) + ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on, true) }) } @@ -213,7 +214,7 @@ where ) -> bool { self.probe(|| { EvalCtxt::enter_root(self, self.cx().recursion_limit(), I::Span::dummy(), |ecx| { - ecx.evaluate_goal(GoalSource::Misc, goal, None) + ecx.evaluate_goal(GoalSource::Misc, goal, None, true) }) .is_ok_and(|r| match r.certainty { Certainty::Yes => true, @@ -232,7 +233,7 @@ where ) -> bool { self.probe(|| { EvalCtxt::enter_root(self, root_depth, I::Span::dummy(), |ecx| { - ecx.evaluate_goal(GoalSource::Misc, goal, None) + ecx.evaluate_goal(GoalSource::Misc, goal, None, true) }) }) .is_ok() @@ -413,9 +414,10 @@ where source: GoalSource, goal: Goal, stalled_on: Option>, + is_root_goal: bool, ) -> Result, NoSolution> { let (normalization_nested_goals, goal_evaluation) = - self.evaluate_goal_raw(source, goal, stalled_on)?; + self.evaluate_goal_raw(source, goal, stalled_on, is_root_goal)?; assert!(normalization_nested_goals.is_empty()); Ok(goal_evaluation) } @@ -432,6 +434,7 @@ where source: GoalSource, goal: Goal, stalled_on: Option>, + is_root_goal: bool, ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolution> { // If we have run this goal before, and it was stalled, check that any of the goal's // args have changed. Otherwise, we don't need to re-run the goal because it'll remain @@ -480,11 +483,33 @@ where let has_changed = if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; + // FIXME: We should revisit and consider removing this after + // *assumptions on binders* is available, like once we had done in the + // stabilization of `-Znext-solver=coherence`(#121848). + // We ignore constraints from the nested goals in leak check. This is to match + // with the old solver's behavior, which has separated evaluation and fulfillment, + // and the former doesn't consider outlives obligations from the later. + let vis = if is_root_goal { + VisibleForLeakCheck::Yes + } else { + match goal.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(_) + | ty::PredicateKind::DynCompatible(_) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::NormalizesTo(_) => VisibleForLeakCheck::No, + ty::PredicateKind::AliasRelate(_, _, _) => VisibleForLeakCheck::Yes, + } + }; + let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response( self.delegate, goal.param_env, &orig_values, response, + vis, self.origin_span, ); @@ -676,7 +701,7 @@ where let ( NestedNormalizationGoals(nested_goals), GoalEvaluation { goal, certainty, stalled_on, has_changed: _ }, - ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on)?; + ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on, false)?; // Add the nested goals from normalization to our own nested goals. trace!(?nested_goals); self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None))); @@ -729,7 +754,7 @@ where } } else { let GoalEvaluation { goal, certainty, has_changed, stalled_on } = - self.evaluate_goal(source, goal, stalled_on)?; + self.evaluate_goal(source, goal, stalled_on, false)?; if has_changed == HasChanged::Yes { unchanged_certainty = None; } @@ -1092,13 +1117,18 @@ where args } - pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { - self.delegate.register_ty_outlives(ty, lt, self.origin_span); + pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region, vis: VisibleForLeakCheck) { + self.delegate.register_ty_outlives(ty, lt, vis, self.origin_span); } - pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) { + pub(super) fn register_region_outlives( + &self, + a: I::Region, + b: I::Region, + vis: VisibleForLeakCheck, + ) { // `'a: 'b` ==> `'b <= 'a` - self.delegate.sub_regions(b, a, self.origin_span); + self.delegate.sub_regions(b, a, vis, self.origin_span); } /// Computes the list of goals required for `arg` to be well-formed @@ -1296,7 +1326,7 @@ where let mut unique = HashSet::default(); external_constraints .region_constraints - .retain(|outlives| !outlives.is_trivial() && unique.insert(*outlives)); + .retain(|(outlives, _)| !outlives.is_trivial() && unique.insert(*outlives)); let canonical = canonicalize_response( self.delegate, @@ -1527,6 +1557,7 @@ pub(super) fn evaluate_root_goal_for_proof_tree, goal.param_env, &proof_tree.orig_values, response, + VisibleForLeakCheck::Yes, origin_span, ); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 793d45f22d39b..ce58a300d9555 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -91,7 +91,7 @@ where goal: Goal>, ) -> QueryResult { let ty::OutlivesPredicate(ty, lt) = goal.predicate; - self.register_ty_outlives(ty, lt); + self.register_ty_outlives(ty, lt, VisibleForLeakCheck::Yes); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -101,7 +101,7 @@ where goal: Goal>, ) -> QueryResult { let ty::OutlivesPredicate(a, b) = goal.predicate; - self.register_region_outlives(a, b); + self.register_region_outlives(a, b, VisibleForLeakCheck::Yes); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 05ecc4725a7b6..bacdf8e9c64db 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -112,6 +112,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< SubregionOrigin::RelateRegionParamBound(span, None), outlives.1, outlives.0, + ty::VisibleForLeakCheck::Yes, ); Some(Certainty::Yes) } @@ -119,6 +120,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.register_type_outlives_constraint( outlives.0, outlives.1, + ty::VisibleForLeakCheck::Yes, &ObligationCause::dummy_with_span(span), ); @@ -204,7 +206,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect()) } - fn make_deduplicated_region_constraints(&self) -> Vec> { + fn make_deduplicated_region_constraints( + &self, + ) -> Vec<(ty::RegionConstraint<'tcx>, ty::VisibleForLeakCheck)> { // Cannot use `take_registered_region_obligations` as we may compute the response // inside of a `probe` whenever we have multiple choices inside of the solver. let region_obligations = self.0.inner.borrow().region_obligations().to_owned(); @@ -221,8 +225,8 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< region_constraints .constraints .into_iter() - .filter(|&(outlives, _)| seen.insert(outlives)) - .map(|(outlives, _)| outlives) + .filter(|&(outlives, _, vis)| seen.insert((outlives, vis))) + .map(|(outlives, _, vis)| (outlives, vis)) .collect() } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index f28e6f32b5f86..c337def9f0eb0 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -738,7 +738,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); selcx.infcx.enter_forall(binder, |pred| { - selcx.infcx.register_region_outlives_constraint(pred, &dummy_cause); + selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause); }); } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => { @@ -751,6 +751,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { selcx.infcx.register_type_outlives_constraint( t_a, selcx.infcx.tcx.lifetimes.re_static, + ty::VisibleForLeakCheck::Yes, &dummy_cause, ); } @@ -758,6 +759,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { selcx.infcx.register_type_outlives_constraint( t_a, r_b, + ty::VisibleForLeakCheck::Yes, &dummy_cause, ); } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 11ff9911469e1..eed36605a34af 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -459,7 +459,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => { if infcx.considering_regions { - infcx.register_region_outlives_constraint(data, &obligation.cause); + infcx.register_region_outlives_constraint( + data, + ty::VisibleForLeakCheck::Yes, + &obligation.cause, + ); } ProcessResult::Changed(Default::default()) @@ -470,7 +474,12 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { r_b, ))) => { if infcx.considering_regions { - infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause); + infcx.register_type_outlives_constraint( + t_a, + r_b, + ty::VisibleForLeakCheck::Yes, + &obligation.cause, + ); } ProcessResult::Changed(Default::default()) } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 8bbdc9d76c514..8be26fed0ca42 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -83,13 +83,13 @@ fn implied_outlives_bounds<'a, 'tcx>( // outlives bound required proving some higher-ranked coroutine obl. let QueryRegionConstraints { constraints, assumptions: _ } = constraints; let cause = ObligationCause::misc(span, body_id); - for &(constraint, _) in &constraints { + for &(constraint, _, vis) in &constraints { match constraint { ty::RegionConstraint::Outlives(predicate) => { - infcx.register_outlives_constraint(predicate, &cause) + infcx.register_outlives_constraint(predicate, vis, &cause) } ty::RegionConstraint::Eq(predicate) => { - infcx.register_region_eq_constraint(predicate, &cause) + infcx.register_region_eq_constraint(predicate, vis, &cause) } } } diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 0dd4ea823c949..83a77f17b28ce 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -80,7 +80,7 @@ fn compute_assumptions<'tcx>( tcx.mk_outlives_from_iter( constraints .into_iter() - .flat_map(|(constraint, _)| constraint.iter_outlives()) + .flat_map(|(constraint, _, _)| constraint.iter_outlives()) // FIXME(higher_ranked_auto): We probably should deeply resolve these before // filtering out infers which only correspond to unconstrained infer regions // which we can sometimes get. diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 905b005cd48f8..5581b70fcec4d 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -8,6 +8,7 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; +use crate::solve::VisibleForLeakCheck; use crate::{self as ty, Interner, TyVid}; /// The current typing mode of an inference context. We unfortunately have some @@ -323,6 +324,7 @@ pub trait InferCtxtLike: Sized { &self, sub: ::Region, sup: ::Region, + vis: VisibleForLeakCheck, span: ::Span, ); @@ -330,6 +332,7 @@ pub trait InferCtxtLike: Sized { &self, a: ::Region, b: ::Region, + vis: VisibleForLeakCheck, span: ::Span, ); @@ -337,6 +340,7 @@ pub trait InferCtxtLike: Sized { &self, ty: ::Ty, r: ::Region, + vis: VisibleForLeakCheck, span: ::Span, ); diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 9064f13eb45e9..857738d207b4f 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -58,6 +58,7 @@ TrivialTypeTraversalImpls! { crate::solve::BuiltinImplSource, crate::solve::Certainty, crate::solve::GoalSource, + crate::solve::VisibleForLeakCheck, rustc_ast_ir::Mutability, // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 82ee4f75fcb0a..a643d22c17643 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -4,7 +4,7 @@ use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combi use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; -use crate::solve::Goal; +use crate::solve::{Goal, VisibleForLeakCheck}; use crate::{self as ty, InferCtxtLike, Interner}; pub trait RelateExt: InferCtxtLike { @@ -256,10 +256,10 @@ where fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { match self.ambient_variance { // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) - ty::Covariant => self.infcx.sub_regions(b, a, self.span), + ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) - ty::Contravariant => self.infcx.sub_regions(a, b, self.span), - ty::Invariant => self.infcx.equate_regions(a, b, self.span), + ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span), + ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span), ty::Bivariant => { unreachable!("Expected bivariance to be handled in relate_with_variance") } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index fe779b66dc245..7f2575d0f4f79 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -253,7 +253,7 @@ impl Eq for Response {} #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct ExternalConstraintsData { - pub region_constraints: Vec>, + pub region_constraints: Vec<(ty::RegionConstraint, VisibleForLeakCheck)>, pub opaque_types: Vec<(ty::OpaqueTypeKey, I::Ty)>, pub normalization_nested_goals: NestedNormalizationGoals, } @@ -268,6 +268,25 @@ impl ExternalConstraintsData { } } +/// Whether the given region constraint should be considered/ignored for +/// leak check. In most part of the compiler, this should be `Yes`, except +/// for applying constraints from the nested goals in next-solver. +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub enum VisibleForLeakCheck { + Yes, + No, +} + +impl VisibleForLeakCheck { + pub fn and(self, other: VisibleForLeakCheck) -> VisibleForLeakCheck { + match (self, other) { + (VisibleForLeakCheck::Yes, VisibleForLeakCheck::Yes) => VisibleForLeakCheck::Yes, + (VisibleForLeakCheck::No, _) | (_, VisibleForLeakCheck::No) => VisibleForLeakCheck::No, + } + } +} + #[derive_where(Clone, Hash, PartialEq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] diff --git a/tests/crashes/140577.rs b/tests/crashes/140577.rs deleted file mode 100644 index 21e6b1e1522fb..0000000000000 --- a/tests/crashes/140577.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ known-bug: #140577 -//@ compile-flags: -Znext-solver=globally -//@ edition:2021 - -use std::future::Future; -use std::pin::Pin; -trait Acquire { - type Connection; -} -impl Acquire for &'static () { - type Connection = (); -} -fn b() -> impl Future + Send { - let x: Pin + Send>> = todo!(); - x -} -fn main() { - async { - b::<&()>().await; - } - .aa(); -} - -impl Filter for F where F: Send {} - -trait Filter { - fn aa(self) - where - Self: Sized, - { - } -} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr index 6fcf1b1eac176..eaf7a84b28043 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr @@ -1,21 +1,21 @@ -error: implementation of `Foo` is not general enough +error[E0308]: mismatched types --> $DIR/higher-ranked-auto-trait-10.rs:32:5 | LL | Box::new(async move { get_foo(x).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + = note: expected enum `Result<&_, _>` + found enum `Result<&_, _>` -error: implementation of `Foo` is not general enough +error: implementation of `Send` is not general enough --> $DIR/higher-ranked-auto-trait-10.rs:32:5 | LL | Box::new(async move { get_foo(x).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough | - = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: `Send` would have to be implemented for the type `&str` + = note: ...but `Send` is actually implemented for the type `&'0 str`, for some specific lifetime `'0` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr index 6fcf1b1eac176..eaf7a84b28043 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr @@ -1,21 +1,21 @@ -error: implementation of `Foo` is not general enough +error[E0308]: mismatched types --> $DIR/higher-ranked-auto-trait-10.rs:32:5 | LL | Box::new(async move { get_foo(x).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + = note: expected enum `Result<&_, _>` + found enum `Result<&_, _>` -error: implementation of `Foo` is not general enough +error: implementation of `Send` is not general enough --> $DIR/higher-ranked-auto-trait-10.rs:32:5 | LL | Box::new(async move { get_foo(x).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough | - = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: `Send` would have to be implemented for the type `&str` + = note: ...but `Send` is actually implemented for the type `&'0 str`, for some specific lifetime `'0` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr index d39843f628c46..c45b8ddc6fa47 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr @@ -13,8 +13,8 @@ error: implementation of `Send` is not general enough LL | Box::pin(async move { >::foo().await }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough | - = note: `Send` would have to be implemented for the type `>::Future`, for any lifetime `'0`... - = note: ...but `Send` is actually implemented for the type `>::Future`, for some specific lifetime `'1` + = note: `>::Future` must implement `Send`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `>::Future` error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr index d39843f628c46..c45b8ddc6fa47 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr @@ -13,8 +13,8 @@ error: implementation of `Send` is not general enough LL | Box::pin(async move { >::foo().await }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough | - = note: `Send` would have to be implemented for the type `>::Future`, for any lifetime `'0`... - = note: ...but `Send` is actually implemented for the type `>::Future`, for some specific lifetime `'1` + = note: `>::Future` must implement `Send`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `>::Future` error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index cfbdaa8ad4beb..890ab66739fa7 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -17,14 +17,14 @@ LL | assert_send(my_send_async_method(struct_with_lifetime, data)); = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: implementation of `Callable` is not general enough +error: implementation of `Send` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Callable` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough | - = note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... - = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` + = note: `Send` would have to be implemented for the type `&Vec` + = note: ...but `Send` is actually implemented for the type `&'0 Vec`, for some specific lifetime `'0` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 @@ -54,7 +54,6 @@ LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | = note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index 8fa3c7483c89d..a7101b7b077c4 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -6,8 +6,8 @@ LL | | call_me.call().await; LL | | }); | |______^ implementation of `Send` is not general enough | - = note: `Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... - = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` + = note: `Send` would have to be implemented for the type `&Wrap>` + = note: ...but `Send` is actually implemented for the type `&'0 Wrap>`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/closure-upvar-named-lifetime.stderr b/tests/ui/borrowck/closure-upvar-named-lifetime.stderr index fc7c59fa97c89..5e0a06fbdc22d 100644 --- a/tests/ui/borrowck/closure-upvar-named-lifetime.stderr +++ b/tests/ui/borrowck/closure-upvar-named-lifetime.stderr @@ -73,6 +73,9 @@ LL | f(value); | -------- argument requires that `map` is borrowed for `'a` LL | } | - `map` dropped here while still borrowed + | +note: requirement that the value outlives `'a` introduced here + --> $SRC_DIR/core/src/ops/function.rs:LL:COL error[E0716]: temporary value dropped while borrowed --> $DIR/closure-upvar-named-lifetime.rs:34:21 @@ -87,6 +90,9 @@ LL | let value = map.borrow_mut().entry("foo".to_string()); ... LL | f(value); | -------- argument requires that borrow lasts for `'a` + | +note: requirement that the value outlives `'a` introduced here + --> $SRC_DIR/core/src/ops/function.rs:LL:COL error[E0700]: hidden type for `impl Fn(RefCell>)` captures lifetime that does not appear in bounds --> $DIR/closure-upvar-named-lifetime.rs:32:5 diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index 646abaf4f7bde..82c1f45d432f7 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -4,8 +4,8 @@ error: implementation of `Coroutine` is not general enough LL | test(gen); | ^^^^^^^^^ implementation of `Coroutine` is not general enough | - = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:28: 11:44}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... - = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` + = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:28: 11:44}` must implement `Coroutine<&'1 mut bool>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Coroutine<&mut bool>` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr index 2e7e8c12e671e..48da168dc50ed 100644 --- a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr @@ -1,10 +1,10 @@ -error: higher-ranked lifetime error +error: lifetime bound not satisfied --> $DIR/must-prove-where-clauses-on-norm.rs:23:61 | LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; | ^^^^^^^^^ | - = note: could not normalize `for<'b> fn(<() as Trait>::Assoc<'_, 'b>, &'b str) -> &str` + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr index ab51e2bdae77f..27418eb05dc7d 100644 --- a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr @@ -2,12 +2,10 @@ error[E0308]: mismatched types --> $DIR/must-prove-where-clauses-on-norm.rs:23:61 | LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; - | ------------------------------------------- ^^^^^^^^^ one type is more general than the other - | | - | expected due to this + | ^^^^^^^^^ one type is more general than the other | - = note: expected fn pointer `for<'b> fn((), &'b _) -> &'static _` - found fn item `for<'b> fn(<() as Trait>::Assoc<'_, 'b>, &'b _) -> &_ {foo::<'_, ()>}` + = note: expected fn pointer `for<'b> fn((), &'b _) -> &_` + found fn pointer `for<'b> fn((), &'b _) -> &_` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs index 064ed18248206..fb2da8efb4084 100644 --- a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs @@ -21,7 +21,7 @@ fn foo<'a, 'b, T: Trait>(_: ::Assoc<'a, 'b>, x: &'b str) -> &'a str fn main() { let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; - //[current]~^ ERROR higher-ranked lifetime error + //[current]~^ ERROR lifetime bound not satisfied //[next]~^^ ERROR mismatched types let x: &'static str = func((), &String::from("temporary")); println!("{x}"); diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr index ddfc94da1354c..dcf0ed0931995 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr @@ -1,14 +1,8 @@ -error[E0271]: type mismatch resolving `>::Assoc == usize` - --> $DIR/candidate-from-env-universe-err-project.rs:38:24 +error: higher-ranked subtype error + --> $DIR/candidate-from-env-universe-err-project.rs:38:5 | LL | projection_bound::(); - | ^ types differ - | -note: required by a bound in `projection_bound` - --> $DIR/candidate-from-env-universe-err-project.rs:19:42 - | -LL | fn projection_bound Trait<'a, Assoc = usize>>() {} - | ^^^^^^^^^^^^^ required by this bound in `projection_bound` + | ^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error --> $DIR/candidate-from-env-universe-err-project.rs:52:30 @@ -26,4 +20,3 @@ LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs index dd6da62a47272..2dce218f5b83b 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs @@ -36,7 +36,7 @@ fn function2>() { // does not use the leak check when trying the where-bound, causing us // to prefer it over the impl, resulting in a placeholder error. projection_bound::(); - //[next]~^ ERROR type mismatch resolving `>::Assoc == usize` + //[next]~^ ERROR higher-ranked subtype error //[current]~^^ ERROR mismatched types } diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index 327c0faa48287..0aa15643532e0 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -60,7 +60,7 @@ LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + = note: ...but it actually implements `Bar<&isize>` warning: function cannot return without recursing --> $DIR/hrtb-perfect-forwarding.rs:48:1 diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr index b2bb417a8f01b..d78db07253d89 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'a &'0 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&&str,)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 @@ -13,8 +13,8 @@ error: implementation of `FnOnce` is not general enough LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'a &'0 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&&str,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -23,8 +23,8 @@ error: implementation of `FnOnce` is not general enough LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'a Wrapper<'0>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'_>,)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 @@ -32,8 +32,8 @@ error: implementation of `FnOnce` is not general enough LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'a Wrapper<'0>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr deleted file mode 100644 index 96c76ca9ac311..0000000000000 --- a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/normalization-preserve-equality.rs:24:1 - | -LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { - | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | | - | | | lifetime `'b` defined here - | | lifetime `'a` defined here - | requires that `'a` must outlive `'b` - | - = help: consider adding the following bound: `'a: 'b` - -error: lifetime may not live long enough - --> $DIR/normalization-preserve-equality.rs:24:1 - | -LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { - | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | | - | | | lifetime `'b` defined here - | | lifetime `'a` defined here - | requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - -help: `'a` and `'b` must be the same: replace one with the other - -error: aborting due to 2 previous errors - diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.rs b/tests/ui/implied-bounds/normalization-preserve-equality.rs index 712c8ce945df0..d4c83994702bd 100644 --- a/tests/ui/implied-bounds/normalization-preserve-equality.rs +++ b/tests/ui/implied-bounds/normalization-preserve-equality.rs @@ -1,9 +1,5 @@ -// Both revisions should pass. `borrowck` revision is a bug! -// +//@ check-pass //@ revisions: wfcheck borrowck -//@ [wfcheck] check-pass -//@ [borrowck] check-fail -//@ [borrowck] known-bug: #106569 struct Equal<'a, 'b>(&'a &'b (), &'b &'a ()); // implies 'a == 'b diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 4b3d0e8ac5efc..01a8494d7afe7 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'0 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 @@ -13,8 +13,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `for<'a> fn(&'0 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -23,8 +23,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -32,8 +32,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&u32, &'0 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -41,8 +41,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -51,8 +51,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&u32, &'0 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32, &u32, u32)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 78f6ce882dfab..9804bce4eaeb9 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -22,8 +22,8 @@ error: implementation of `FnOnce` is not general enough LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&i32,)>` error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 @@ -31,8 +31,8 @@ error: implementation of `Fn` is not general enough LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&i32,)>` error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:11:5 diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 8adde8d6dfbf3..13731ebf43aa5 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 u32)` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32,)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 @@ -13,8 +13,8 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 u32)` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 4dada6ff014ad..80a2387b384c6 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -48,8 +48,8 @@ error: implementation of `Fn` is not general enough LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` + = note: `fn(&'0 T) -> &'0 T {identity::<&'0 T>}` must implement `Fn<(&'1 T,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&T,)>` error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 @@ -57,8 +57,8 @@ error: implementation of `FnOnce` is not general enough LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` + = note: `fn(&'0 T) -> &'0 T {identity::<&'0 T>}` must implement `FnOnce<(&'1 T,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&T,)>` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 62e872639671b..4926ab1225d9d 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -69,8 +69,8 @@ error: implementation of `Fn` is not general enough LL | baz(f); | ^^^^^^ implementation of `Fn` is not general enough | - = note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` + = note: `fn(*mut &'0 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(*mut &u32,)>` error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 @@ -78,8 +78,8 @@ error: implementation of `FnOnce` is not general enough LL | baz(f); | ^^^^^^ implementation of `FnOnce` is not general enough | - = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + = note: `fn(*mut &'0 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(*mut &u32,)>` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 378fe83ea89bd..dfdd14b9c59a2 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | baz(|_| ()); | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:12:5 @@ -13,8 +13,8 @@ error: implementation of `Fn` is not general enough LL | baz(|_| ()); | ^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `Fn<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:16:5 @@ -22,8 +22,8 @@ error: implementation of `FnOnce` is not general enough LL | baz(|x| ()); | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:16:5 @@ -31,8 +31,8 @@ error: implementation of `Fn` is not general enough LL | baz(|x| ()); | ^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `Fn<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&(),)>` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 629570b602ed6..a10697a4a0cfd 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -37,8 +37,8 @@ error: implementation of `FnOnce` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&mut V,)>` error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -46,8 +46,8 @@ error: implementation of `Fn` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `Fn<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&mut V,)>` error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -55,8 +55,8 @@ error: implementation of `FnOnce` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&mut V,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Fn` is not general enough @@ -65,8 +65,8 @@ error: implementation of `Fn` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `Fn<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&mut V,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -75,8 +75,8 @@ error: implementation of `FnOnce` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&mut V,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Fn` is not general enough @@ -85,8 +85,8 @@ error: implementation of `Fn` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 mut V)` must implement `Fn<(&'1 mut V,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&mut V,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 10 previous errors diff --git a/tests/ui/nll/issue-57843.stderr b/tests/ui/nll/issue-57843.stderr index eed511460cac7..d73396dc3b763 100644 --- a/tests/ui/nll/issue-57843.stderr +++ b/tests/ui/nll/issue-57843.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | Foo(Box::new(|_| ())); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 bool)` must implement `FnOnce<(&'1 bool,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&bool,)>` error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-69114-static-ty.stderr b/tests/ui/nll/issue-69114-static-ty.stderr index a77ae85162187..d8b09bba4cf20 100644 --- a/tests/ui/nll/issue-69114-static-ty.stderr +++ b/tests/ui/nll/issue-69114-static-ty.stderr @@ -11,6 +11,9 @@ LL | FOO(&n); LL | LL | } | - `n` dropped here while still borrowed + | +note: requirement that the value outlives `'static` introduced here + --> $SRC_DIR/core/src/ops/function.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index c2e91edd13872..758fe5a9089ee 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | accept(callback); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 @@ -13,8 +13,8 @@ error: implementation of `FnOnce` is not general enough LL | accept(callback); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -23,8 +23,8 @@ error: implementation of `FnOnce` is not general enough LL | accept(callback); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough @@ -33,8 +33,8 @@ error: implementation of `FnOnce` is not general enough LL | accept(callback); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 804b3f00a2642..0a0c0f829fffa 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -30,8 +30,8 @@ error: implementation of `Fn` is not general enough LL | bad(&b); | ^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -39,8 +39,8 @@ error: implementation of `FnOnce` is not general enough LL | bad(&b); | ^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` error: aborting due to 3 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 804b3f00a2642..0a0c0f829fffa 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -30,8 +30,8 @@ error: implementation of `Fn` is not general enough LL | bad(&b); | ^^^^^^^ implementation of `Fn` is not general enough | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -39,8 +39,8 @@ error: implementation of `FnOnce` is not general enough LL | bad(&b); | ^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'0 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` error: aborting due to 3 previous errors diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.rs b/tests/ui/nll/ty-outlives/projection-where-clause-none.rs index bb201e5c0754c..3e518695d7761 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-none.rs +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.rs @@ -11,7 +11,7 @@ fn foo<'a, T>() -> &'a () where T: MyTrait<'a>, { - bar::() //~ ERROR the parameter type `T` may not live long enough + bar::() //~ ERROR the associated type `>::Output` may not live long enough } fn bar<'a, T>() -> &'a () diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr index b4136be36d315..8aa8a1dadea97 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -1,16 +1,16 @@ -error[E0309]: the parameter type `T` may not live long enough +error[E0309]: the associated type `>::Output` may not live long enough --> $DIR/projection-where-clause-none.rs:14:5 | LL | fn foo<'a, T>() -> &'a () - | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... + | -- the associated type `>::Output` must be valid for the lifetime `'a` as defined here... ... LL | bar::() - | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ ...so that the type `>::Output` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | -LL | T: MyTrait<'a> + 'a, - | ++++ +LL | T: MyTrait<'a>, >::Output: 'a + | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr index 5c98a9d4fb4ce..d49c4d2cf54ca 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr @@ -4,8 +4,8 @@ error: implementation of `Fn` is not general enough LL | f: &id, | ^^^ implementation of `Fn` is not general enough | - = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `Fn<(&'1 Foo<'b>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` + = note: `fn(&'0 Foo<'_>) -> &'0 Foo<'_> {id::<&'0 Foo<'_>>}` must implement `Fn<(&'1 Foo<'b>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&Foo<'_>,)>` error: implementation of `Fn` is not general enough --> $DIR/rfc1623-2.rs:28:8 @@ -13,8 +13,8 @@ error: implementation of `Fn` is not general enough LL | f: &id, | ^^^ implementation of `Fn` is not general enough | - = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `Fn<(&'a Foo<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `Fn<(&Foo<'2>,)>`, for some specific lifetime `'2` + = note: `fn(&Foo<'0>) -> &Foo<'0> {id::<&Foo<'0>>}` must implement `Fn<(&'a Foo<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Fn<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623-2.rs:28:8 @@ -22,8 +22,8 @@ error: implementation of `FnOnce` is not general enough LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough | - = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` + = note: `fn(&'0 Foo<'_>) -> &'0 Foo<'_> {id::<&'0 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623-2.rs:28:8 @@ -31,8 +31,8 @@ error: implementation of `FnOnce` is not general enough LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough | - = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2` + = note: `fn(&Foo<'0>) -> &Foo<'0> {id::<&Foo<'0>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Foo<'_>,)>` error: aborting due to 4 previous errors diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr index 77072656c3366..9266fffdbabb4 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr @@ -11,6 +11,12 @@ LL | z = f::>(&s); LL | LL | } | - `s` dropped here while still borrowed + | +note: requirement that the value outlives `'static` introduced here + --> $DIR/check-trait-object-bounds-3.rs:7:13 + | +LL | fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str { + | ^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-1.rs b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-1.rs new file mode 100644 index 0000000000000..7c20246e5eb71 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-1.rs @@ -0,0 +1,43 @@ +//@ check-pass +//@ compile-flags: -Znext-solver=globally +//@ edition:2021 + +// Regression test for . +// +// This previously caused an ICE due to a non–well-formed coroutine +// hidden type failing the leak check in the next-solver. +// +// In `TypingMode::Analysis`, the problematic type is hidden behind a +// stalled coroutine candidate. However, in later passes (e.g. MIR +// validation), we eagerly normalize it. The candidate that was +// previously accepted as a solution then fails the leak check, resulting +// in broken MIR and ultimately an ICE. + +use std::future::Future; +use std::pin::Pin; +trait Acquire { + type Connection; +} +impl Acquire for &'static () { + type Connection = (); +} +fn b() -> impl Future + Send { + let x: Pin + Send>> = todo!(); + x +} +fn main() { + async { + b::<&()>().await; + } + .aa(); +} + +impl Filter for F where F: Send {} + +trait Filter { + fn aa(self) + where + Self: Sized, + { + } +} diff --git a/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-2.rs b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-2.rs new file mode 100644 index 0000000000000..004775b822976 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-2.rs @@ -0,0 +1,48 @@ +//@ check-pass +//@ compile-flags: -Znext-solver -Zvalidate-mir +//@ edition: 2021 + +// Regression test for . +// +// This previously caused an ICE due to a non–well-formed coroutine +// hidden type failing the leak check in the next-solver. +// +// In `TypingMode::Analysis`, the problematic type is hidden behind a +// stalled coroutine candidate. However, in later passes (e.g. MIR +// validation), we eagerly normalize it. The candidate that was +// previously accepted as a solution then fails the leak check, resulting +// in broken MIR and ultimately an ICE. + +use std::future::Future; + +trait Access { + // has to have an associated type, but can be anything + type Reader; + + fn read(&self) -> impl Future + Send { + async { loop {} } + } +} + +trait AccessDyn: Sync {} +impl Access for dyn AccessDyn { + type Reader = (); +} + +trait Stream { + fn poll_next(s: &'static dyn AccessDyn); +} + +// has to be a function in a trait impl, can't be a normal impl block or standalone fn +impl Stream for () { + fn poll_next(s: &'static dyn AccessDyn) { + // new async block is important + is_dyn_send(&async { + s.read().await; + }); + } +} + +fn is_dyn_send(_: &dyn Send) {} + +fn main() {} diff --git a/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-3.rs b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-3.rs new file mode 100644 index 0000000000000..7de6ec519eaa5 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-candidate-behind-stalled-coroutine-3.rs @@ -0,0 +1,34 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +//@ edition:2021 + +// Regression test for . +// +// This previously caused an ICE due to a non–well-formed coroutine +// hidden type failing the leak check in the next-solver. +// +// In `TypingMode::Analysis`, the problematic type is hidden behind a +// stalled coroutine candidate. However, in later passes (e.g. MIR +// validation), we eagerly normalize it. The candidate that was +// previously accepted as a solution then fails the leak check, resulting +// in broken MIR and ultimately an ICE. + +trait Trait { + type Assoc; +} +impl Trait for &'static u32 { + type Assoc = (); +} +struct W(T::Assoc); + +fn prove_send_and_hide(x: T) -> impl Send { x } +fn as_dyn_send(_: &dyn Send) {} +pub fn main() { + // Checking whether the cast to the trait object is correct + // during MIR validation uses `TypingMode::PostAnalysis` and + // therefore looks into the opaque. + as_dyn_send(&async move { + let opaque_ty = prove_send_and_hide(W::<&'static u32>(())); + std::future::ready(opaque_ty).await; + }); +} diff --git a/tests/ui/traits/vtable/lack-of-implied-bounds-for-opaque-types-unsound.rs b/tests/ui/traits/vtable/lack-of-implied-bounds-for-opaque-types-unsound.rs new file mode 100644 index 0000000000000..e071510976a14 --- /dev/null +++ b/tests/ui/traits/vtable/lack-of-implied-bounds-for-opaque-types-unsound.rs @@ -0,0 +1,45 @@ +//@ run-pass + +// Regression test for . + +#![allow(warnings)] + +trait Trait { + type Assoc; +} +impl<'a, 'b: 'a> Trait for Inv<'a, 'b> { + type Assoc = (); +} + +trait ReqWf {} +impl ReqWf for T where T::Assoc: Sized {} +struct Inv<'a, 'b: 'a>(Option<*mut &'a &'b ()>); +fn mk_opaque<'a, 'b>(x: &'a &'b u32) -> impl ReqWf + use<'a, 'b> { + Inv::<'a, 'b>(None) +} + +trait Bound {} +impl Bound for F where F: FnOnce(T) -> R {} +trait ImpossiblePredicates { + fn call_me(&self) + where + F: for<'a, 'b> Bound<&'a &'b u32>, + { + println!("method body"); + } +} +impl ImpossiblePredicates for () {} +fn mk_trait_object(_: F) -> Box> { + Box::new(()) +} +pub fn main() { + let obj = mk_trait_object(mk_opaque); + // This previously caused a segfault: the where-bounds of + // `ImpossiblePredicate::call_me` did not hold due to missing implied bounds + // for the fully normalized opaque type of `obj` in `fn impossible_predicates`. + // As a result, the method's vtable ended up empty. + // + // However, earlier compilation passes did not report an error because the + // opaque type had not yet been fully normalized. + obj.call_me(); +} diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 0815ae1fb5a2b..29a0a8317040e 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -4,8 +4,8 @@ error: implementation of `FnOnce` is not general enough LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` + = note: `fn(&'0 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&str,)>` error: aborting due to 1 previous error