From 0689a4f4f719418ee4fba74aa39d7920104343b5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 22 Mar 2024 12:09:53 +0000 Subject: [PATCH 01/13] Add regression test --- tests/ui/impl-trait/nested-hkl-lifetime.rs | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/ui/impl-trait/nested-hkl-lifetime.rs diff --git a/tests/ui/impl-trait/nested-hkl-lifetime.rs b/tests/ui/impl-trait/nested-hkl-lifetime.rs new file mode 100644 index 0000000000000..089ceca6777a3 --- /dev/null +++ b/tests/ui/impl-trait/nested-hkl-lifetime.rs @@ -0,0 +1,32 @@ +//@ check-pass + +use std::iter::FromIterator; + +struct DynamicAlt

(P); + +impl

FromIterator

for DynamicAlt

{ + fn from_iter>(_iter: T) -> Self { + loop {} + } +} + +fn owned_context(_: F) -> impl FnMut(I) -> I { + |i| i +} + +trait Parser {} + +impl Parser for T where T: FnMut(I) -> I {} + +fn alt>(_: DynamicAlt

) -> impl FnMut(I) -> I { + |i| i +} + +fn rule_to_parser<'c>() -> impl Parser<&'c str> { + move |input| { + let v: Vec<()> = vec![]; + alt(v.iter().map(|()| owned_context(rule_to_parser())).collect::>())(input) + } +} + +fn main() {} From ea44ce059b9f10394a08e369cd856192984d0ca0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 22 Mar 2024 12:18:08 +0000 Subject: [PATCH 02/13] Make `Canonical` trait impls more robust --- compiler/rustc_type_ir/src/canonical.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index ad18ef249842f..3da74f9fe6e7c 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -63,28 +63,30 @@ impl Eq for Canonical {} impl PartialEq for Canonical { fn eq(&self, other: &Self) -> bool { - self.value == other.value - && self.max_universe == other.max_universe - && self.variables == other.variables + let Self { value, max_universe, variables } = self; + *value == other.value + && *max_universe == other.max_universe + && *variables == other.variables } } impl fmt::Display for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { value, max_universe, variables } = self; write!( f, - "Canonical {{ value: {}, max_universe: {:?}, variables: {:?} }}", - self.value, self.max_universe, self.variables + "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?} }}", ) } } impl fmt::Debug for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { value, max_universe, variables } = self; f.debug_struct("Canonical") - .field("value", &self.value) - .field("max_universe", &self.max_universe) - .field("variables", &self.variables) + .field("value", &value) + .field("max_universe", &max_universe) + .field("variables", &variables) .finish() } } @@ -109,9 +111,10 @@ where I::CanonicalVars: TypeVisitable, { fn visit_with>(&self, folder: &mut F) -> F::Result { - try_visit!(self.value.visit_with(folder)); - try_visit!(self.max_universe.visit_with(folder)); - self.variables.visit_with(folder) + let Self { value, max_universe, variables } = self; + try_visit!(value.visit_with(folder)); + try_visit!(max_universe.visit_with(folder)); + variables.visit_with(folder) } } From 19bd91d128d921522287314925c027ea4aea1e45 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Mar 2024 10:21:27 +0000 Subject: [PATCH 03/13] Pass list of defineable opaque types into canonical queries --- .../src/region_infer/opaque_types.rs | 12 ++++++++++ .../src/infer/canonical/canonicalizer.rs | 9 +++++++- compiler/rustc_infer/src/infer/mod.rs | 16 ++++++------- .../rustc_infer/src/infer/opaque_types/mod.rs | 2 -- compiler/rustc_middle/src/infer/canonical.rs | 11 ++++----- compiler/rustc_middle/src/query/plumbing.rs | 8 +++---- compiler/rustc_middle/src/traits/mod.rs | 15 ++++++------ compiler/rustc_middle/src/traits/solve.rs | 3 +-- compiler/rustc_middle/src/ty/context.rs | 1 + .../src/canonicalizer.rs | 3 ++- compiler/rustc_trait_selection/src/infer.rs | 7 +++--- .../src/solve/eval_ctxt/canonical.rs | 1 - .../src/solve/eval_ctxt/mod.rs | 1 - .../rustc_trait_selection/src/solve/mod.rs | 1 + compiler/rustc_type_ir/src/canonical.rs | 23 +++++++++++-------- compiler/rustc_type_ir/src/debug.rs | 4 ++++ compiler/rustc_type_ir/src/infcx.rs | 2 ++ compiler/rustc_type_ir/src/interner.rs | 1 + .../equality-in-canonical-query.clone.stderr | 23 ------------------- .../impl-trait/equality-in-canonical-query.rs | 11 +-------- tests/ui/impl-trait/nested-rpit-hrtb.rs | 2 +- tests/ui/impl-trait/nested-rpit-hrtb.stderr | 7 +++--- .../issue-53398-cyclic-types.rs | 3 +-- .../issue-53398-cyclic-types.stderr | 9 ++++++++ ...equality_in_canonical_query.current.stderr | 23 ------------------- .../rpit_tait_equality_in_canonical_query.rs | 12 +--------- .../type-alias-impl-trait-with-cycle-error.rs | 6 ++--- ...e-alias-impl-trait-with-cycle-error.stderr | 11 ++++----- ...type-alias-impl-trait-with-cycle-error2.rs | 2 +- ...-alias-impl-trait-with-cycle-error2.stderr | 11 ++++----- 30 files changed, 101 insertions(+), 139 deletions(-) delete mode 100644 tests/ui/impl-trait/equality-in-canonical-query.clone.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr delete mode 100644 tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 63b8044581747..1979554332e72 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -133,6 +133,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { let ty = infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type); + + // Sometimes, when the hidden type is an inference variable, it can happen that + // the hidden type becomes the opaque type itself. In this case, this was an opaque + // usage of the opaque type and we can ignore it. This check is mirrored in typeck's + // writeback. + // FIXME(-Znext-solver): This should be unnecessary with the new solver. + if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() + && alias_ty.def_id == opaque_type_key.def_id.to_def_id() + && alias_ty.args == opaque_type_key.args + { + continue; + } // Sometimes two opaque types are the same only after we remap the generic parameters // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to `(X, Y)` // and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we only know that diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9f70fee993dfe..370028db88b6b 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -45,6 +45,7 @@ impl<'tcx> InferCtxt<'tcx> { let param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, + self.defining_use_anchor, query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the @@ -540,6 +541,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: (), + defining_anchor: infcx.map(|i| i.defining_use_anchor).unwrap_or_default(), }; Canonicalizer::canonicalize_with_base( base, @@ -609,7 +611,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { .max() .unwrap_or(ty::UniverseIndex::ROOT); - Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) } + Canonical { + max_universe, + variables: canonical_variables, + value: (base.value, out_value), + defining_anchor: base.defining_anchor, + } } /// Creates a canonical variable replacing `kind` from the input, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6e5ed0a31cb10..0a43f7cfa2903 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -243,13 +243,7 @@ impl<'tcx> InferCtxtInner<'tcx> { pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, - /// The `DefId` of the item in whose context we are performing inference or typeck. - /// It is used to check whether an opaque type use is a defining use. - /// - /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up - /// the obligation. This frequently happens for - /// short lived InferCtxt within queries. The opaque type obligations are forwarded - /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. + /// The `DefIds` of the opaque types that may have their hidden types constrained. /// /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined. /// This way it is easier to catch errors that @@ -401,6 +395,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { fn probe_ct_var(&self, vid: ConstVid) -> Option> { self.probe_const_var(vid).ok() } + + fn defining_anchor(&self) -> DefiningAnchor<'tcx> { + self.defining_use_anchor + } } /// See the `error_reporting` module for more details. @@ -679,14 +677,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// the bound values in `C` to their instantiated values in `V` /// (in other words, `S(C) = V`). pub fn build_with_canonical( - &mut self, + self, span: Span, canonical: &Canonical<'tcx, T>, ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>) where T: TypeFoldable>, { - let infcx = self.build(); + let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build(); let (value, args) = infcx.instantiate_canonical(span, canonical); (infcx, value, args) } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 01430e830e556..e199aec2eb614 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -146,7 +146,6 @@ impl<'tcx> InferCtxt<'tcx> { return None; } } - DefiningAnchor::Bubble => {} } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't @@ -373,7 +372,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { let defined_opaque_types = match self.defining_use_anchor { - DefiningAnchor::Bubble => return None, DefiningAnchor::Bind(bind) => bind, }; diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index acea89e4aabec..2a51cfc5e7c36 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -33,6 +33,7 @@ use std::ops::Index; use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; +use crate::traits::DefiningAnchor; use crate::ty::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; @@ -153,11 +154,6 @@ pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, pub certainty: Certainty, - /// List of opaque types which we tried to compare to another type. - /// Inside the query we don't know yet whether the opaque type actually - /// should get its hidden type inferred. So we bubble the opaque type - /// and the type it was compared against upwards and let the query caller - /// handle it. pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, pub value: R, } @@ -316,6 +312,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: ty::ParamEnv<'tcx>, + defining_anchor: DefiningAnchor<'tcx>, state: &mut OriginalQueryValues<'tcx>, canonicalize_op: fn( TyCtxt<'tcx>, @@ -330,6 +327,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: key, + defining_anchor, }; } @@ -344,7 +342,8 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { *canonical } Entry::Vacant(e) => { - let canonical = canonicalize_op(tcx, key, state); + let mut canonical = canonicalize_op(tcx, key, state); + canonical.defining_anchor = defining_anchor; let OriginalQueryValues { var_values, universe_map } = state; assert_eq!(universe_map.len(), 1); e.insert((canonical, tcx.arena.alloc_slice(var_values))); diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 8cb4ee7bd41e0..b14ecad83cc57 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -338,10 +338,10 @@ macro_rules! define_callbacks { pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; - // Ensure that keys grow no larger than 64 bytes + // Ensure that keys grow no larger than 72 bytes #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 64 { + if mem::size_of::>() > 72 { panic!("{}", concat!( "the query `", stringify!($name), @@ -352,10 +352,10 @@ macro_rules! define_callbacks { } }; - // Ensure that values grow no larger than 64 bytes + // Ensure that values grow no larger than 72 bytes #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 64 { + if mem::size_of::>() > 72 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index ee81679191978..58aff27266d1d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -1004,6 +1004,7 @@ pub enum CodegenObligationError { /// opaques are replaced with inference vars eagerly in the old solver (e.g. /// in projection, and in the signature during function type-checking). #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable)] pub enum DefiningAnchor<'tcx> { /// Define opaques which are in-scope of the current item being analyzed. /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`. @@ -1012,14 +1013,12 @@ pub enum DefiningAnchor<'tcx> { /// errors when handling opaque types, and also should be used when we would /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). Bind(&'tcx ty::List), - /// In contexts where we don't currently know what opaques are allowed to be - /// defined, such as (old solver) canonical queries, we will simply allow - /// opaques to be defined, but "bubble" them up in the canonical response or - /// otherwise treat them to be handled later. - /// - /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`, - /// which may affect what predicates pass and fail in the old trait solver. - Bubble, +} + +impl Default for DefiningAnchor<'_> { + fn default() -> Self { + Self::Bind(ty::List::empty()) + } } impl<'tcx> DefiningAnchor<'tcx> { diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 6dcea2aaff1af..13504c6ae930a 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -4,7 +4,7 @@ use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; -use crate::traits::{Canonical, DefiningAnchor}; +use crate::traits::Canonical; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, @@ -114,7 +114,6 @@ impl MaybeCause { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct QueryInput<'tcx, T> { pub goal: Goal<'tcx, T>, - pub anchor: DefiningAnchor<'tcx>, pub predefined_opaques_in_body: PredefinedOpaques<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1db9bce73a6a8..36fad95715c85 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -84,6 +84,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; + type DefiningAnchor = traits::DefiningAnchor<'tcx>; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; type GenericArg = ty::GenericArg<'tcx>; diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 1899517c0e248..2be1db51da1bd 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -69,7 +69,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc let (max_universe, variables) = canonicalizer.finalize(); - Canonical { max_universe, variables, value } + let defining_anchor = infcx.defining_anchor(); + Canonical { defining_anchor, max_universe, variables, value } } fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 7056288e758c8..0595e82b39ed4 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,5 +1,5 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext}; +use crate::traits::{self, ObligationCtxt, SelectionContext}; use crate::traits::TraitEngineExt as _; use rustc_hir::def_id::DefId; @@ -132,9 +132,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> { R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { - let (infcx, key, canonical_inference_vars) = self - .with_opaque_type_inference(DefiningAnchor::Bubble) - .build_with_canonical(DUMMY_SP, canonical_key); + let (infcx, key, canonical_inference_vars) = + self.build_with_canonical(DUMMY_SP, canonical_key); let ocx = ObligationCtxt::new(&infcx); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 4a4efb6884fc5..0b37163d59702 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -68,7 +68,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut orig_values, QueryInput { goal, - anchor: self.infcx.defining_use_anchor, predefined_opaques_in_body: self .tcx() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 1739bd70e7b5a..5efee7a2190a1 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -230,7 +230,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { .infer_ctxt() .intercrate(intercrate) .with_next_trait_solver(true) - .with_opaque_type_inference(canonical_input.value.anchor) .build_with_canonical(DUMMY_SP, &canonical_input); let mut ecx = EvalCtxt { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 8294a8a67b14c..311deee0dbcf0 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -316,5 +316,6 @@ fn response_no_constraints_raw<'tcx>( external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), certainty, }, + defining_anchor: Default::default(), } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 3da74f9fe6e7c..1134935e02d15 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,6 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, + pub defining_anchor: I::DefiningAnchor, pub variables: I::CanonicalVars, } @@ -44,8 +45,8 @@ impl Canonical { /// let b: Canonical)> = a.unchecked_map(|v| (v, ty)); /// ``` pub fn unchecked_map(self, map_op: impl FnOnce(V) -> W) -> Canonical { - let Canonical { max_universe, variables, value } = self; - Canonical { max_universe, variables, value: map_op(value) } + let Canonical { defining_anchor, max_universe, variables, value } = self; + Canonical { defining_anchor, max_universe, variables, value: map_op(value) } } /// Allows you to map the `value` of a canonical while keeping the same set of @@ -54,8 +55,8 @@ impl Canonical { /// **WARNING:** This function is very easy to mis-use, hence the name! See /// the comment of [Canonical::unchecked_map] for more details. pub fn unchecked_rebind(self, value: W) -> Canonical { - let Canonical { max_universe, variables, value: _ } = self; - Canonical { max_universe, variables, value } + let Canonical { defining_anchor, max_universe, variables, value: _ } = self; + Canonical { defining_anchor, max_universe, variables, value } } } @@ -63,30 +64,32 @@ impl Eq for Canonical {} impl PartialEq for Canonical { fn eq(&self, other: &Self) -> bool { - let Self { value, max_universe, variables } = self; + let Self { value, max_universe, variables, defining_anchor } = self; *value == other.value && *max_universe == other.max_universe && *variables == other.variables + && *defining_anchor == other.defining_anchor } } impl fmt::Display for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { value, max_universe, variables } = self; + let Self { value, max_universe, variables, defining_anchor } = self; write!( f, - "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?} }}", + "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_anchor: {defining_anchor:?} }}", ) } } impl fmt::Debug for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { value, max_universe, variables } = self; + let Self { value, max_universe, variables, defining_anchor } = self; f.debug_struct("Canonical") .field("value", &value) .field("max_universe", &max_universe) .field("variables", &variables) + .field("defining_anchor", &defining_anchor) .finish() } } @@ -102,6 +105,7 @@ where value: self.value.try_fold_with(folder)?, max_universe: self.max_universe.try_fold_with(folder)?, variables: self.variables.try_fold_with(folder)?, + defining_anchor: self.defining_anchor, }) } } @@ -111,9 +115,10 @@ where I::CanonicalVars: TypeVisitable, { fn visit_with>(&self, folder: &mut F) -> F::Result { - let Self { value, max_universe, variables } = self; + let Self { value, max_universe, variables, defining_anchor } = self; try_visit!(value.visit_with(folder)); try_visit!(max_universe.visit_with(folder)); + try_visit!(defining_anchor.visit_with(folder)); variables.visit_with(folder) } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 9c8e45b4338c6..aced3b53fde29 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -43,6 +43,10 @@ impl InferCtxtLike for NoInfcx { fn probe_ct_var(&self, _vid: ConstVid) -> Option { None } + + fn defining_anchor(&self) -> ::DefiningAnchor { + Default::default() + } } pub trait DebugWithInfcx: fmt::Debug { diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index 28b71f0ea13f8..bdfa010c00035 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -37,4 +37,6 @@ pub trait InferCtxtLike { /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type. fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; + + fn defining_anchor(&self) -> ::DefiningAnchor; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 7d6862726f05f..c447f65a5aa43 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -11,6 +11,7 @@ use crate::{ pub trait Interner: Sized + Copy { type DefId: Copy + Debug + Hash + Eq; + type DefiningAnchor: Copy + Debug + Hash + Default + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; type GenericArgs: Copy diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr deleted file mode 100644 index e4c8aec397365..0000000000000 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ /dev/null @@ -1,23 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }} - | - = - - -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }))), bound_vars: [] } } } - --> $DIR/equality-in-canonical-query.rs:21:5 - | -LL | same_output(foo, rpit); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - - --> $DIR/equality-in-canonical-query.rs:21:5 - | -LL | same_output(foo, rpit); - | ^^^^^^^^^^^^^^^^^^^^^^ - -query stack during panic: -end of query stack diff --git a/tests/ui/impl-trait/equality-in-canonical-query.rs b/tests/ui/impl-trait/equality-in-canonical-query.rs index 6a32f4bec76d4..2b8f6ce1b0753 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.rs +++ b/tests/ui/impl-trait/equality-in-canonical-query.rs @@ -1,15 +1,6 @@ // issue: #116877 //@ revisions: sized clone -//@[sized] check-pass -//@[clone] known-bug: #108498 -//@[clone] failure-status: 101 -//@[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//@[clone] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: delayed at.*$" -> "" -//@[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" -//@[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> "" +//@ check-pass #[cfg(sized)] fn rpit() -> impl Sized {} #[cfg(clone)] fn rpit() -> impl Clone {} diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs index a696e1710f065..9b18aceb4a731 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.rs +++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs @@ -44,7 +44,7 @@ fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized // This should resolve. fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} -//~^ ERROR type annotations needed: cannot satisfy `for<'a> &'a (): Qux<'b>` +//~^ ERROR the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied // This should resolve. fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {} diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 64f801ea6851f..2fa036f35fab3 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -86,13 +86,12 @@ note: lifetime declared here LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} | ^^ -error[E0283]: type annotations needed: cannot satisfy `for<'a> &'a (): Qux<'b>` +error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied --> $DIR/nested-rpit-hrtb.rs:46:79 | LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()` | - = note: cannot satisfy `for<'a> &'a (): Qux<'b>` = help: the trait `Qux<'_>` is implemented for `()` = help: for that trait implementation, expected `()`, found `&'a ()` @@ -125,5 +124,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si error: aborting due to 11 previous errors -Some errors have detailed explanations: E0261, E0277, E0283, E0657. +Some errors have detailed explanations: E0261, E0277, E0657. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs index ae463b6ef5b8e..9cc8546afbce7 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -1,10 +1,9 @@ #![feature(type_alias_impl_trait)] -//@ check-pass - type Foo = impl Fn() -> Foo; fn foo() -> Foo { + //~^ ERROR: overflow foo } diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr new file mode 100644 index 0000000000000..1358c3e2a98b8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == Foo` + --> $DIR/issue-53398-cyclic-types.rs:5:13 + | +LL | fn foo() -> Foo { + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr deleted file mode 100644 index 1c36fda4ae14b..0000000000000 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ /dev/null @@ -1,23 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} - | - = - - -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } - --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - | - - --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - -query stack during panic: -end of query stack diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs index 7524cebf9e638..6f50703aca24d 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -8,17 +8,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass - -//@[current] known-bug: #108498 -//@[current] failure-status: 101 -//@[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//@[current] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: delayed at.*$" -> "" -//@[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" -//@[current] normalize-stderr-test: "(?m)^ *at .*\n" -> "" +//@ check-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs index e5e7fb677ede9..80ab53881a328 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -1,12 +1,10 @@ #![feature(type_alias_impl_trait)] type Foo = impl Fn() -> Foo; -//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { + //~^ ERROR: overflow x } -fn main() { - -} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr index 3d43fbe0dbccb..21779c7d1284a 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12 +error[E0275]: overflow evaluating the requirement `>::Output == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error.rs:5:21 | -LL | type Foo = impl Fn() -> Foo; - | ^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs index 7c7a1b405bcdc..87b2d6765f4e2 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -5,9 +5,9 @@ pub trait Bar { } type Foo = impl Bar; -//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { + //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr index e2dc887989b29..d1c620968ba90 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12 +error[E0275]: overflow evaluating the requirement `>::Item == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:9:21 | -LL | type Foo = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. From b2b5fa825dff427f87c577e605eaa5d382364909 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Mar 2024 10:34:03 +0000 Subject: [PATCH 04/13] Eagerly check for accidentally registered region constraints instead of waiting until borrowck is done --- compiler/rustc_borrowck/src/type_check/canonical.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index f28b786e4f739..a950f10787b36 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -39,6 +39,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx, locations.span(self.body))?; + if cfg!(debug_assertions) { + let data = self.infcx.take_and_reset_region_constraints(); + if !data.is_empty() { + panic!("leftover region constraints: {data:#?}"); + } + } debug!(?output, ?constraints); From 08e25e45364e58e598206f1e198b4b534d50d37c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Mar 2024 18:07:30 +0000 Subject: [PATCH 05/13] Adjust a comment to the new status quo --- .../rustc_infer/src/infer/canonical/query_response.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 9d2e065afa37e..b948067e750eb 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -505,12 +505,9 @@ impl<'tcx> InferCtxt<'tcx> { let b = instantiate_value(self.tcx, &result_args, b); debug!(?a, ?b, "constrain opaque type"); // We use equate here instead of, for example, just registering the - // opaque type's hidden value directly, because we may be instantiating - // a query response that was canonicalized in an InferCtxt that had - // a different defining anchor. In that case, we may have inferred - // `NonLocalOpaque := LocalOpaque` but can only instantiate it in - // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq - // here allows us to try both directions (in `InferCtxt::handle_opaque_type`). + // opaque type's hidden value directly, because the hidden type may have been an inference + // variable that got constrained to the opaque type itself. In that case we want to equate + // the generic args of the opaque with the generic params of its hidden type version. obligations.extend( self.at(cause, param_env) .eq( From dd72bf922adae10276013b408c96f913331916e8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Mar 2024 18:06:53 +0000 Subject: [PATCH 06/13] Scrape extraneous regions from instantiate_nll_query_response_and_region_obligations --- .../src/traits/query/type_op/mod.rs | 103 ++++++++++-------- .../ui/inference/issue-80409.no-compat.stderr | 2 +- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index faf218131b8b1..ae4cdb9258e29 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -159,53 +159,70 @@ where .0); } + let mut error_info = None; let mut region_constraints = QueryRegionConstraints::default(); - let (output, error_info, mut obligations, _) = - Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| { - infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}")) - })?; - - // Typically, instantiating NLL query results does not - // create obligations. However, in some cases there - // are unresolved type variables, and unify them *can* - // create obligations. In that case, we have to go - // fulfill them. We do this via a (recursive) query. - while !obligations.is_empty() { - trace!("{:#?}", obligations); - let mut progress = false; - for obligation in std::mem::take(&mut obligations) { - let obligation = infcx.resolve_vars_if_possible(obligation); - match ProvePredicate::fully_perform_into( - obligation.param_env.and(ProvePredicate::new(obligation.predicate)), - infcx, - &mut region_constraints, - span, - ) { - Ok(((), _, new, certainty)) => { - obligations.extend(new); - progress = true; - if let Certainty::Ambiguous = certainty { - obligations.push(obligation); + + // HACK(type_alias_impl_trait): When moving an opaque type to hidden type mapping from the query to the current inferctxt, + // we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a + // hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually + // collecting region constraints via `region_constraints`. + let (mut output, _) = scrape_region_constraints( + infcx, + |_ocx| { + let (output, ei, mut obligations, _) = + Q::fully_perform_into(self, infcx, &mut region_constraints, span)?; + error_info = ei; + + // Typically, instantiating NLL query results does not + // create obligations. However, in some cases there + // are unresolved type variables, and unify them *can* + // create obligations. In that case, we have to go + // fulfill them. We do this via a (recursive) query. + while !obligations.is_empty() { + trace!("{:#?}", obligations); + let mut progress = false; + for obligation in std::mem::take(&mut obligations) { + let obligation = infcx.resolve_vars_if_possible(obligation); + match ProvePredicate::fully_perform_into( + obligation.param_env.and(ProvePredicate::new(obligation.predicate)), + infcx, + &mut region_constraints, + span, + ) { + Ok(((), _, new, certainty)) => { + obligations.extend(new); + progress = true; + if let Certainty::Ambiguous = certainty { + obligations.push(obligation); + } + } + Err(_) => obligations.push(obligation), } } - Err(_) => obligations.push(obligation), + if !progress { + infcx.dcx().span_bug( + span, + format!("ambiguity processing {obligations:?} from {self:?}"), + ); + } } - } - if !progress { - infcx - .dcx() - .span_bug(span, format!("ambiguity processing {obligations:?} from {self:?}")); - } - } - - Ok(TypeOpOutput { - output, - constraints: if region_constraints.is_empty() { - None - } else { - Some(infcx.tcx.arena.alloc(region_constraints)) + Ok(output) }, - error_info, - }) + "fully_perform", + span, + )?; + output.error_info = error_info; + if let Some(constraints) = output.constraints { + region_constraints + .member_constraints + .extend(constraints.member_constraints.iter().cloned()); + region_constraints.outlives.extend(constraints.outlives.iter().cloned()); + } + output.constraints = if region_constraints.is_empty() { + None + } else { + Some(infcx.tcx.arena.alloc(region_constraints)) + }; + Ok(output) } } diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr index 523ca229b06f4..c772225be7549 100644 --- a/tests/ui/inference/issue-80409.no-compat.stderr +++ b/tests/ui/inference/issue-80409.no-compat.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } } +error: internal compiler error: error performing operation: fully_perform --> $DIR/issue-80409.rs:49:30 | LL | builder.state().on_entry(|_| {}); From 2f2350e57720112c61d393bc98720ee0a59074df Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 10:29:11 +0000 Subject: [PATCH 07/13] Eliminate `DefiningAnchor` now that is just a single-variant enum --- compiler/rustc_borrowck/src/consumers.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 3 +- .../src/region_infer/opaque_types.rs | 7 +- .../rustc_hir_analysis/src/check/check.rs | 9 +- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 7 +- compiler/rustc_infer/src/infer/at.rs | 2 +- .../src/infer/canonical/canonicalizer.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 34 ++++---- .../rustc_infer/src/infer/opaque_types/mod.rs | 85 +++++++++---------- compiler/rustc_middle/src/infer/canonical.rs | 8 +- compiler/rustc_middle/src/traits/mod.rs | 31 +------ compiler/rustc_middle/src/ty/codec.rs | 6 ++ compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/list.rs | 6 ++ .../src/canonicalizer.rs | 4 +- .../rustc_trait_selection/src/solve/mod.rs | 2 +- compiler/rustc_type_ir/src/canonical.rs | 28 +++--- compiler/rustc_type_ir/src/debug.rs | 2 +- compiler/rustc_type_ir/src/infcx.rs | 2 +- compiler/rustc_type_ir/src/interner.rs | 2 +- 20 files changed, 109 insertions(+), 140 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 31307ef14102e..64726eacca74a 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::{Body, Promoted}; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::TyCtxt; use std::rc::Rc; @@ -106,7 +105,7 @@ pub fn get_body_with_borrowck_facts( options: ConsumerOptions, ) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap() diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4a5ba4418783e..8037a7223e772 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -32,7 +32,6 @@ use rustc_infer::infer::{ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; @@ -126,7 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 1979554332e72..9f0e54febe4cd 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -7,7 +7,6 @@ use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_macros::extension; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{GenericArgKind, GenericArgs}; @@ -333,13 +332,13 @@ fn check_opaque_type_well_formed<'tcx>( parent_def_id = tcx.local_parent(parent_def_id); } - // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])` + // FIXME(-Znext-solver): We probably should use `&[]` instead of // and prepopulate this `InferCtxt` with known opaque values, rather than - // using the `Bind` anchor here. For now it's fine. + // allowing opaque types to be defined and checking them after the fact. let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id)) + .with_opaque_type_inference(parent_def_id) .build(); let ocx = ObligationCtxt::new(&infcx); let identity_args = GenericArgs::identity_for_item(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 739a708699239..8d4ae10d4bfe6 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode}; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; @@ -345,10 +345,7 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - let infcx = tcx - .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor)) - .build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build(); let ocx = ObligationCtxt::new(&infcx); let args = match *origin { @@ -1567,7 +1564,7 @@ pub(super) fn check_coroutine_obligations( .ignoring_regions() // Bind opaque types to type checking root, as they should have been checked by borrowck, // but may show up in some cases, like when (root) obligations are stalled in the new solver. - .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id)) + .with_opaque_type_inference(typeck.hir_owner.def_id) .build(); let mut fulfillment_cx = >::new(&infcx); diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index e493e6a0a7ed9..6808b993ee9d5 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -5,7 +5,6 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; @@ -78,11 +77,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id)) - .build(); + let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); TypeckRootCtxt { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 94088216c029a..f2222eec76af2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -75,7 +75,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn fork_with_intercrate(&self, intercrate: bool) -> Self { Self { tcx: self.tcx, - defining_use_anchor: self.defining_use_anchor, + defining_opaque_types: self.defining_opaque_types, considering_regions: self.considering_regions, skip_leak_check: self.skip_leak_check, inner: self.inner.clone(), diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 370028db88b6b..9986fdfd15d1c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -45,7 +45,7 @@ impl<'tcx> InferCtxt<'tcx> { let param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, - self.defining_use_anchor, + self.defining_opaque_types, query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the @@ -541,7 +541,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: (), - defining_anchor: infcx.map(|i| i.defining_use_anchor).unwrap_or_default(), + defining_opaque_types: infcx.map(|i| i.defining_opaque_types).unwrap_or_default(), }; Canonicalizer::canonicalize_with_base( base, @@ -615,7 +615,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe, variables: canonical_variables, value: (base.value, out_value), - defining_anchor: base.defining_anchor, + defining_opaque_types: base.defining_opaque_types, } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0a43f7cfa2903..aaf389c93debc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::traits::{select, DefiningAnchor}; +use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -244,11 +244,7 @@ pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, /// The `DefIds` of the opaque types that may have their hidden types constrained. - /// - /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined. - /// This way it is easier to catch errors that - /// might come up during inference or typeck. - pub defining_use_anchor: DefiningAnchor<'tcx>, + pub defining_opaque_types: &'tcx ty::List, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -396,8 +392,8 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { self.probe_const_var(vid).ok() } - fn defining_anchor(&self) -> DefiningAnchor<'tcx> { - self.defining_use_anchor + fn defining_opaque_types(&self) -> &'tcx ty::List { + self.defining_opaque_types } } @@ -613,7 +609,7 @@ impl fmt::Display for FixupError { /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, - defining_use_anchor: DefiningAnchor<'tcx>, + defining_opaque_types: &'tcx ty::List, considering_regions: bool, skip_leak_check: bool, /// Whether we are in coherence mode. @@ -628,7 +624,7 @@ impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, - defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()), + defining_opaque_types: ty::List::empty(), considering_regions: true, skip_leak_check: false, intercrate: false, @@ -644,8 +640,16 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// It is only meant to be called in two places, for typeck /// (via `Inherited::build`) and for the inference context used /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self { - self.defining_use_anchor = defining_use_anchor; + pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self { + self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor); + self + } + + pub fn with_defining_opaque_types( + mut self, + defining_opaque_types: &'tcx ty::List, + ) -> Self { + self.defining_opaque_types = defining_opaque_types; self } @@ -684,7 +688,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { where T: TypeFoldable>, { - let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build(); + let infcx = self.with_defining_opaque_types(canonical.defining_opaque_types).build(); let (value, args) = infcx.instantiate_canonical(span, canonical); (infcx, value, args) } @@ -692,7 +696,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { pub fn build(&mut self) -> InferCtxt<'tcx> { let InferCtxtBuilder { tcx, - defining_use_anchor, + defining_opaque_types, considering_regions, skip_leak_check, intercrate, @@ -700,7 +704,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } = *self; InferCtxt { tcx, - defining_use_anchor, + defining_opaque_types, considering_regions, skip_leak_check, inner: RefCell::new(InferCtxtInner::new()), diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index e199aec2eb614..52d495bcff061 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -8,7 +8,7 @@ use hir::OpaqueTyOrigin; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_middle::traits::{DefiningAnchor, ObligationCause}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::GenericArgKind; @@ -106,47 +106,44 @@ impl<'tcx> InferCtxt<'tcx> { b, )); } - match self.defining_use_anchor { - DefiningAnchor::Bind(_) => { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if self.opaque_type_origin(def_id).is_none() { - return None; - } - } + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + if self.opaque_type_origin(def_id).is_none() { + return None; } + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't // want to make a decision on it right now. Likely this case is so super rare anyway, that @@ -371,13 +368,9 @@ impl<'tcx> InferCtxt<'tcx> { /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let defined_opaque_types = match self.defining_use_anchor { - DefiningAnchor::Bind(bind) => bind, - }; - let origin = self.tcx.opaque_type_origin(def_id); - defined_opaque_types.contains(&def_id).then_some(origin) + self.defining_opaque_types.contains(&def_id).then_some(origin) } } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 2a51cfc5e7c36..fac132686f8e9 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,6 +23,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; +use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; use rustc_type_ir::Canonical as IrCanonical; use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; @@ -33,7 +34,6 @@ use std::ops::Index; use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; -use crate::traits::DefiningAnchor; use crate::ty::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; @@ -312,7 +312,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: ty::ParamEnv<'tcx>, - defining_anchor: DefiningAnchor<'tcx>, + defining_opaque_types: &'tcx ty::List, state: &mut OriginalQueryValues<'tcx>, canonicalize_op: fn( TyCtxt<'tcx>, @@ -327,7 +327,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: key, - defining_anchor, + defining_opaque_types, }; } @@ -343,7 +343,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { } Entry::Vacant(e) => { let mut canonical = canonicalize_op(tcx, key, state); - canonical.defining_anchor = defining_anchor; + canonical.defining_opaque_types = defining_opaque_types; let OriginalQueryValues { var_values, universe_map } = state; assert_eq!(universe_map.len(), 1); e.insert((canonical, tcx.arena.alloc_slice(var_values))); diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 58aff27266d1d..d51e86c909c50 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -12,8 +12,8 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; +use crate::ty::GenericArgsRef; use crate::ty::{self, AdtKind, Ty}; -use crate::ty::{GenericArgsRef, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diag, EmissionGuarantee}; @@ -997,32 +997,3 @@ pub enum CodegenObligationError { Unimplemented, FulfillmentError, } - -/// Defines the treatment of opaque types in a given inference context. -/// -/// This affects both what opaques are allowed to be defined, but also whether -/// opaques are replaced with inference vars eagerly in the old solver (e.g. -/// in projection, and in the signature during function type-checking). -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -#[derive(TyEncodable, TyDecodable)] -pub enum DefiningAnchor<'tcx> { - /// Define opaques which are in-scope of the current item being analyzed. - /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`. - /// - /// If the list is empty, do not allow any opaques to be defined. This is used to catch type mismatch - /// errors when handling opaque types, and also should be used when we would - /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). - Bind(&'tcx ty::List), -} - -impl Default for DefiningAnchor<'_> { - fn default() -> Self { - Self::Bind(ty::List::empty()) - } -} - -impl<'tcx> DefiningAnchor<'tcx> { - pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { - Self::Bind(tcx.opaque_types_defined_by(item)) - } -} diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 9068961d73605..9b158459cd113 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -443,6 +443,12 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> Decodable for &'tcx ty::List { + fn decode(d: &mut D) -> Self { + RefDecodable::decode(d) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List<(VariantIdx, FieldIdx)> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 36fad95715c85..562698084bdaa 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -84,7 +84,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; - type DefiningAnchor = traits::DefiningAnchor<'tcx>; + type DefiningOpaqueTypes = &'tcx ty::List; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; type GenericArg = ty::GenericArg<'tcx>; diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 04e165c8a73af..0db541899d20e 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -55,6 +55,12 @@ struct ListSkeleton { data: [T; 0], } +impl Default for &List { + fn default() -> Self { + List::empty() + } +} + extern "C" { /// A dummy type used to force `List` to be unsized while not requiring /// references to it be wide pointers. diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 2be1db51da1bd..57dc792255c2c 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -69,8 +69,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc let (max_universe, variables) = canonicalizer.finalize(); - let defining_anchor = infcx.defining_anchor(); - Canonical { defining_anchor, max_universe, variables, value } + let defining_opaque_types = infcx.defining_opaque_types(); + Canonical { defining_opaque_types, max_universe, variables, value } } fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 311deee0dbcf0..da5cd15a10d71 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -316,6 +316,6 @@ fn response_no_constraints_raw<'tcx>( external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), certainty, }, - defining_anchor: Default::default(), + defining_opaque_types: Default::default(), } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 1134935e02d15..bdd43af51adad 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,7 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, - pub defining_anchor: I::DefiningAnchor, + pub defining_opaque_types: I::DefiningOpaqueTypes, pub variables: I::CanonicalVars, } @@ -45,8 +45,8 @@ impl Canonical { /// let b: Canonical)> = a.unchecked_map(|v| (v, ty)); /// ``` pub fn unchecked_map(self, map_op: impl FnOnce(V) -> W) -> Canonical { - let Canonical { defining_anchor, max_universe, variables, value } = self; - Canonical { defining_anchor, max_universe, variables, value: map_op(value) } + let Canonical { defining_opaque_types, max_universe, variables, value } = self; + Canonical { defining_opaque_types, max_universe, variables, value: map_op(value) } } /// Allows you to map the `value` of a canonical while keeping the same set of @@ -55,8 +55,8 @@ impl Canonical { /// **WARNING:** This function is very easy to mis-use, hence the name! See /// the comment of [Canonical::unchecked_map] for more details. pub fn unchecked_rebind(self, value: W) -> Canonical { - let Canonical { defining_anchor, max_universe, variables, value: _ } = self; - Canonical { defining_anchor, max_universe, variables, value } + let Canonical { defining_opaque_types, max_universe, variables, value: _ } = self; + Canonical { defining_opaque_types, max_universe, variables, value } } } @@ -64,32 +64,32 @@ impl Eq for Canonical {} impl PartialEq for Canonical { fn eq(&self, other: &Self) -> bool { - let Self { value, max_universe, variables, defining_anchor } = self; + let Self { value, max_universe, variables, defining_opaque_types } = self; *value == other.value && *max_universe == other.max_universe && *variables == other.variables - && *defining_anchor == other.defining_anchor + && *defining_opaque_types == other.defining_opaque_types } } impl fmt::Display for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { value, max_universe, variables, defining_anchor } = self; + let Self { value, max_universe, variables, defining_opaque_types } = self; write!( f, - "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_anchor: {defining_anchor:?} }}", + "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_opaque_types: {defining_opaque_types:?} }}", ) } } impl fmt::Debug for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { value, max_universe, variables, defining_anchor } = self; + let Self { value, max_universe, variables, defining_opaque_types } = self; f.debug_struct("Canonical") .field("value", &value) .field("max_universe", &max_universe) .field("variables", &variables) - .field("defining_anchor", &defining_anchor) + .field("defining_opaque_types", &defining_opaque_types) .finish() } } @@ -105,7 +105,7 @@ where value: self.value.try_fold_with(folder)?, max_universe: self.max_universe.try_fold_with(folder)?, variables: self.variables.try_fold_with(folder)?, - defining_anchor: self.defining_anchor, + defining_opaque_types: self.defining_opaque_types, }) } } @@ -115,10 +115,10 @@ where I::CanonicalVars: TypeVisitable, { fn visit_with>(&self, folder: &mut F) -> F::Result { - let Self { value, max_universe, variables, defining_anchor } = self; + let Self { value, max_universe, variables, defining_opaque_types } = self; try_visit!(value.visit_with(folder)); try_visit!(max_universe.visit_with(folder)); - try_visit!(defining_anchor.visit_with(folder)); + try_visit!(defining_opaque_types.visit_with(folder)); variables.visit_with(folder) } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index aced3b53fde29..9298360f749ac 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -44,7 +44,7 @@ impl InferCtxtLike for NoInfcx { None } - fn defining_anchor(&self) -> ::DefiningAnchor { + fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes { Default::default() } } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index bdfa010c00035..a53287c19878b 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -38,5 +38,5 @@ pub trait InferCtxtLike { /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type. fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; - fn defining_anchor(&self) -> ::DefiningAnchor; + fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c447f65a5aa43..fa3ccd8e75d2c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -11,7 +11,7 @@ use crate::{ pub trait Interner: Sized + Copy { type DefId: Copy + Debug + Hash + Eq; - type DefiningAnchor: Copy + Debug + Hash + Default + Eq + TypeVisitable; + type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; type GenericArgs: Copy From ba5f0418af3aa6ccb9c876851d73fc4f3039fc61 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 12:27:58 +0000 Subject: [PATCH 08/13] Shrink the size of ClosureTypeInfo to fit into 64 bytes again --- compiler/rustc_middle/src/query/plumbing.rs | 8 +++++--- compiler/rustc_middle/src/ty/closure.rs | 12 ++++++------ compiler/rustc_middle/src/ty/context.rs | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index b14ecad83cc57..6555a6871525a 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -338,7 +338,8 @@ macro_rules! define_callbacks { pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; - // Ensure that keys grow no larger than 72 bytes + // Ensure that keys grow no larger than 72 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))] const _: () = { if mem::size_of::>() > 72 { @@ -352,10 +353,11 @@ macro_rules! define_callbacks { } }; - // Ensure that values grow no larger than 72 bytes + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 72 { + if mem::size_of::>() > 64 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 7db64504f85ea..95d1e08b58b51 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -45,7 +45,7 @@ impl UpvarId { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the @@ -73,7 +73,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap = Vec>; /// A composite describing a `Place` that is captured by a closure. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub struct CapturedPlace<'tcx> { /// Name and span where the binding happens. @@ -192,7 +192,7 @@ impl<'tcx> CapturedPlace<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub struct ClosureTypeInfo<'tcx> { user_provided_sig: ty::CanonicalPolyFnSig<'tcx>, - captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>], + captures: &'tcx ty::List<&'tcx ty::CapturedPlace<'tcx>>, kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>, } @@ -201,7 +201,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo let typeck_results = tcx.typeck(def); let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); - let captures = tcx.arena.alloc_from_iter(captures); + let captures = tcx.mk_captures_from_iter(captures); let hir_id = tcx.local_def_id_to_hir_id(def); let kind_origin = typeck_results.closure_kind_origins().get(hir_id); ClosureTypeInfo { user_provided_sig, captures, kind_origin } @@ -253,7 +253,7 @@ pub fn is_ancestor_or_same_capture( /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind @@ -332,7 +332,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc curr_string } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(Eq, Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 562698084bdaa..f9758738ab21e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -166,6 +166,7 @@ pub struct CtxtInterners<'tcx> { predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>, fields: InternedSet<'tcx, List>, local_def_ids: InternedSet<'tcx, List>, + captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>, offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>, } @@ -193,6 +194,7 @@ impl<'tcx> CtxtInterners<'tcx> { predefined_opaques_in_body: Default::default(), fields: Default::default(), local_def_ids: Default::default(), + captures: Default::default(), offset_of: Default::default(), } } @@ -1906,6 +1908,7 @@ slice_interners!( bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), fields: pub mk_fields(FieldIdx), local_def_ids: intern_local_def_ids(LocalDefId), + captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>), offset_of: pub mk_offset_of((VariantIdx, FieldIdx)), ); @@ -2227,6 +2230,17 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs)) } + pub fn mk_captures_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: CollectAndApply< + &'tcx ty::CapturedPlace<'tcx>, + &'tcx List<&'tcx ty::CapturedPlace<'tcx>>, + >, + { + T::collect_and_apply(iter, |xs| self.intern_captures(xs)) + } + pub fn mk_const_list_from_iter(self, iter: I) -> T::Output where I: Iterator, From 7cfa5219311112a57f812b2a0b78a57624cc73e8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 11:40:28 +0000 Subject: [PATCH 09/13] Avoid fetching the opaque type origin when only "is this in the defining scope" is actually needed --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +-- compiler/rustc_infer/src/infer/mod.rs | 8 ++++++- .../rustc_infer/src/infer/opaque_types/mod.rs | 21 ++++--------------- .../src/solve/eval_ctxt/mod.rs | 6 +++--- .../src/solve/trait_goals.rs | 5 +---- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 85d04f7d1c41e..f1e82543a993a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -730,8 +730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ty in ret_ty.walk() { if let ty::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() - && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id).is_some() + && self.can_define_opaque_ty(def_id) { return None; } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aaf389c93debc..0b8061104ab43 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -244,7 +244,7 @@ pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, /// The `DefIds` of the opaque types that may have their hidden types constrained. - pub defining_opaque_types: &'tcx ty::List, + defining_opaque_types: &'tcx ty::List, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -1232,6 +1232,12 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow().opaque_type_storage.opaque_types.clone() } + #[inline(always)] + pub fn can_define_opaque_ty(&self, id: impl Into) -> bool { + let Some(id) = id.into().as_local() else { return false }; + self.defining_opaque_types.contains(&id) + } + pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { self.resolve_vars_if_possible(t).to_string() } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 52d495bcff061..d32515425c4ba 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -4,7 +4,6 @@ use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, PredicateObligation}; use hir::def_id::{DefId, LocalDefId}; -use hir::OpaqueTyOrigin; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; @@ -54,16 +53,13 @@ impl<'tcx> InferCtxt<'tcx> { } let mut obligations = vec![]; - let replace_opaque_type = |def_id: DefId| { - def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some()) - }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, ty_op: |ty| match *ty.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) - if replace_opaque_type(def_id) && !ty.has_escaping_bound_vars() => + if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() => { let def_span = self.tcx.def_span(def_id); let span = if span.contains(def_span) { def_span } else { span }; @@ -140,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - if self.opaque_type_origin(def_id).is_none() { + if !self.can_define_opaque_ty(def_id) { return None; } @@ -150,8 +146,8 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias { .. }) = - b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) + if self.can_define_opaque_ty(b_def_id) + && self.tcx.is_type_alias_impl_trait(b_def_id) { self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -363,15 +359,6 @@ impl<'tcx> InferCtxt<'tcx> { op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions), }); } - - /// Returns the origin of the opaque type `def_id` if we're currently - /// in its defining scope. - #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let origin = self.tcx.opaque_type_origin(def_id); - - self.defining_opaque_types.contains(&def_id).then_some(origin) - } } /// Visitor that requires that (almost) all regions in the type visited outlive diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 5efee7a2190a1..0154aff12b6e2 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,5 +1,5 @@ use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -935,8 +935,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool { - self.infcx.opaque_type_origin(def_id).is_some() + pub(super) fn can_define_opaque_ty(&self, def_id: impl Into) -> bool { + self.infcx.can_define_opaque_ty(def_id) } pub(super) fn insert_hidden_type( diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index eb3ad0aa782ea..3f04d1d47ccc2 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -155,10 +155,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if matches!(goal.param_env.reveal(), Reveal::All) || matches!(ecx.solver_mode(), SolverMode::Coherence) - || opaque_ty - .def_id - .as_local() - .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) + || ecx.can_define_opaque_ty(opaque_ty.def_id) { return Err(NoSolution); } From cd9453c6377e019a868c4553e0d7bebae1bb24b7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 12:16:51 +0000 Subject: [PATCH 10/13] Mark some tests as known-bugs and add the test case from the corresponding issue --- src/tools/tidy/src/issues.txt | 1 - .../issue-53398-cyclic-types.rs | 10 ----- .../issue-53398-cyclic-types.stderr | 9 ----- ...pe-alias-impl-trait-with-cycle-error-1.rs} | 2 +- ...lias-impl-trait-with-cycle-error-1.stderr} | 2 +- ...pe-alias-impl-trait-with-cycle-error-2.rs} | 2 +- ...lias-impl-trait-with-cycle-error-2.stderr} | 2 +- ...ype-alias-impl-trait-with-cycle-error-3.rs | 10 +++++ ...alias-impl-trait-with-cycle-error-3.stderr | 9 +++++ ...ype-alias-impl-trait-with-cycle-error-4.rs | 16 ++++++++ ...alias-impl-trait-with-cycle-error-4.stderr | 39 +++++++++++++++++++ 11 files changed, 78 insertions(+), 24 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs delete mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error.rs => type-alias-impl-trait-with-cycle-error-1.rs} (82%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error.stderr => type-alias-impl-trait-with-cycle-error-1.stderr} (81%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error2.rs => type-alias-impl-trait-with-cycle-error-2.rs} (86%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error2.stderr => type-alias-impl-trait-with-cycle-error-2.stderr} (80%) create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 060a6fa903f46..e14932ad99d85 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -4132,7 +4132,6 @@ ui/type-alias-impl-trait/issue-52843.rs ui/type-alias-impl-trait/issue-53092-2.rs ui/type-alias-impl-trait/issue-53092.rs ui/type-alias-impl-trait/issue-53096.rs -ui/type-alias-impl-trait/issue-53398-cyclic-types.rs ui/type-alias-impl-trait/issue-53598.rs ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs deleted file mode 100644 index 9cc8546afbce7..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(type_alias_impl_trait)] - -type Foo = impl Fn() -> Foo; - -fn foo() -> Foo { - //~^ ERROR: overflow - foo -} - -fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr deleted file mode 100644 index 1358c3e2a98b8..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == Foo` - --> $DIR/issue-53398-cyclic-types.rs:5:13 - | -LL | fn foo() -> Foo { - | ^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs similarity index 82% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs index 80ab53881a328..19986247d40df 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs @@ -1,9 +1,9 @@ #![feature(type_alias_impl_trait)] +//@ known-bug: #109268 type Foo = impl Fn() -> Foo; fn crash(x: Foo) -> Foo { - //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr similarity index 81% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr index 21779c7d1284a..ee8922b673e2f 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `>::Output == Foo` - --> $DIR/type-alias-impl-trait-with-cycle-error.rs:5:21 + --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21 | LL | fn crash(x: Foo) -> Foo { | ^^^ diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs similarity index 86% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs index 87b2d6765f4e2..761cc83af5106 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs @@ -1,4 +1,5 @@ #![feature(type_alias_impl_trait)] +//@ known-bug: #109268 pub trait Bar { type Item; @@ -7,7 +8,6 @@ pub trait Bar { type Foo = impl Bar; fn crash(x: Foo) -> Foo { - //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr similarity index 80% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr index d1c620968ba90..3d0f1d30ca2b0 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `>::Item == Foo` - --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:9:21 + --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:10:21 | LL | fn crash(x: Foo) -> Foo { | ^^^ diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs new file mode 100644 index 0000000000000..52942afd63922 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] +//@ known-bug: #109268 + +type Foo<'a> = impl Fn() -> Foo<'a>; + +fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr new file mode 100644 index 0000000000000..675689bac4295 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` + --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:6:40 + | +LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs new file mode 100644 index 0000000000000..e866b45a8e61d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] +//@ known-bug: trait-system-refactor-initiative#43 + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + +type Ty +where + Ty: Id, += impl Sized; +fn define() -> Ty {} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr new file mode 100644 index 0000000000000..aedb78bf5e7a1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr @@ -0,0 +1,39 @@ +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:11:1 + | +LL | type Ty + | ^^^^^^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:19 + | +LL | fn define() -> Ty {} + | ^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:16 + | +LL | fn define() -> Ty {} + | ^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. From cd5ca3c7625b2f6ce13a8fd6cda3d656ff5e079a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 16:28:14 +0000 Subject: [PATCH 11/13] Add a FIXME for something that requires touching too much code for this PR --- compiler/rustc_type_ir/src/canonical.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index bdd43af51adad..06a5051956a4b 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,6 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, + // FIXME(lcnr, oli-obk): try moving this into the query inputs instead pub defining_opaque_types: I::DefiningOpaqueTypes, pub variables: I::CanonicalVars, } From c8dfb594061d129e3c7cef7cf4b15ab3c0ab5931 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 26 Mar 2024 11:46:29 +0000 Subject: [PATCH 12/13] bless mir-opt tests --- ..._of_reborrow.SimplifyCfg-initial.after.mir | 60 +++++++++---------- ...ignment.main.SimplifyCfg-initial.after.mir | 4 +- .../issue_101867.main.built.after.mir | 4 +- ...ceiver_ptr_mutability.main.built.after.mir | 8 +-- .../issue_72181_1.main.built.after.mir | 4 +- .../issue_99325.main.built.after.32bit.mir | 4 +- .../issue_99325.main.built.after.64bit.mir | 4 +- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index 76938c14e1ee6..cb72ad3d2531d 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -1,36 +1,36 @@ // MIR for `address_of_reborrow` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:8:5: 8:18, inferred_ty: *const [i32; 10] -| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:10:5: 10:25, inferred_ty: *const dyn std::marker::Send -| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] -| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] -| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] -| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] -| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send -| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send -| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] -| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] -| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:19:5: 19:18, inferred_ty: *const [i32; 10] -| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:21:5: 21:25, inferred_ty: *const dyn std::marker::Send -| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] -| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] -| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] -| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] -| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send -| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send -| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] -| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] -| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:29:5: 29:16, inferred_ty: *mut [i32; 10] -| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:31:5: 31:23, inferred_ty: *mut dyn std::marker::Send -| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] -| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] -| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] -| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] -| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send -| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send -| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] -| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] +| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:8:5: 8:18, inferred_ty: *const [i32; 10] +| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:10:5: 10:25, inferred_ty: *const dyn std::marker::Send +| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] +| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] +| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] +| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] +| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send +| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send +| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] +| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] +| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:19:5: 19:18, inferred_ty: *const [i32; 10] +| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:21:5: 21:25, inferred_ty: *const dyn std::marker::Send +| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] +| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] +| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] +| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] +| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send +| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send +| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] +| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] +| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:29:5: 29:16, inferred_ty: *mut [i32; 10] +| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:31:5: 31:23, inferred_ty: *mut dyn std::marker::Send +| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] +| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] +| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] +| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] +| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send +| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send +| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] +| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] | fn address_of_reborrow() -> () { let mut _0: (); diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index 5df6633880eb0..5c0d1e9b93ffa 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> -| 1: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> +| 0: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> +| 1: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 19a777cb03bc7..0f7917dbb5cbf 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option -| 1: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option +| 0: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option +| 1: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index e07c2b6fa9d1b..1855bb0787d2a 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -1,10 +1,10 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test -| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test -| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test -| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test +| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test +| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test +| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test +| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir index ae0dc9a0b6a2c..e8ad5cd8d16a8 100644 --- a/tests/mir-opt/issue_72181_1.main.built.after.mir +++ b/tests/mir-opt/issue_72181_1.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void -| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void +| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void +| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index c8039dc4735ae..0b0bac73e9f4b 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index c8039dc4735ae..0b0bac73e9f4b 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); From dc97b1eb587fe2db207bfe8c2e914034ab9b9306 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 2 Apr 2024 13:07:13 +0000 Subject: [PATCH 13/13] Ensure the canonical_param_env_cache does not contain inconsistent information about the defining anchor --- .../src/infer/canonical/canonicalizer.rs | 8 ++++-- compiler/rustc_middle/src/infer/canonical.rs | 15 +++++++---- tests/ui/impl-trait/different_where_bounds.rs | 27 +++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 tests/ui/impl-trait/different_where_bounds.rs diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9986fdfd15d1c..2cbf32dca98c9 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -42,10 +42,9 @@ impl<'tcx> InferCtxt<'tcx> { V: TypeFoldable>, { let (param_env, value) = value.into_parts(); - let param_env = self.tcx.canonical_param_env_cache.get_or_insert( + let mut param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, - self.defining_opaque_types, query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the @@ -60,6 +59,8 @@ impl<'tcx> InferCtxt<'tcx> { }, ); + param_env.defining_opaque_types = self.defining_opaque_types; + Canonicalizer::canonicalize_with_base( param_env, value, @@ -611,6 +612,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { .max() .unwrap_or(ty::UniverseIndex::ROOT); + assert!( + !infcx.is_some_and(|infcx| infcx.defining_opaque_types != base.defining_opaque_types) + ); Canonical { max_universe, variables: canonical_variables, diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index fac132686f8e9..62d7b7c28d1fb 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,7 +23,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; -use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; use rustc_type_ir::Canonical as IrCanonical; use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; @@ -312,7 +311,6 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: ty::ParamEnv<'tcx>, - defining_opaque_types: &'tcx ty::List, state: &mut OriginalQueryValues<'tcx>, canonicalize_op: fn( TyCtxt<'tcx>, @@ -327,7 +325,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: key, - defining_opaque_types, + defining_opaque_types: ty::List::empty(), }; } @@ -338,12 +336,19 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { match self.map.borrow().entry(key) { Entry::Occupied(e) => { let (canonical, var_values) = e.get(); + if cfg!(debug_assertions) { + let mut state = state.clone(); + let rerun_canonical = canonicalize_op(tcx, key, &mut state); + assert_eq!(rerun_canonical, *canonical); + let OriginalQueryValues { var_values: rerun_var_values, universe_map } = state; + assert_eq!(universe_map.len(), 1); + assert_eq!(**var_values, *rerun_var_values); + } state.var_values.extend_from_slice(var_values); *canonical } Entry::Vacant(e) => { - let mut canonical = canonicalize_op(tcx, key, state); - canonical.defining_opaque_types = defining_opaque_types; + let canonical = canonicalize_op(tcx, key, state); let OriginalQueryValues { var_values, universe_map } = state; assert_eq!(universe_map.len(), 1); e.insert((canonical, tcx.arena.alloc_slice(var_values))); diff --git a/tests/ui/impl-trait/different_where_bounds.rs b/tests/ui/impl-trait/different_where_bounds.rs new file mode 100644 index 0000000000000..87ae6db28228b --- /dev/null +++ b/tests/ui/impl-trait/different_where_bounds.rs @@ -0,0 +1,27 @@ +//! This test checks that the param env canonicalization cache +//! does not end up with inconsistent values. + +//@ check-pass + +pub fn poison1() -> impl Sized +where + (): 'static, +{ +} +pub fn poison2() -> impl Sized +where + (): 'static, +{ + define_by_query((poison2, ())); +} +pub fn poison3() -> impl Sized +where + (): 'static, +{ +} + +trait Query {} +impl Out> Query for (F, Out) {} +fn define_by_query(_: impl Query) {} + +fn main() {}