From 40d56095486558e8b3a9ff11a0f0298e29c3fd65 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 29 Feb 2024 12:21:20 +0000 Subject: [PATCH 1/6] Make `DefiningAnchor::Bind` only store the opaque types that may be constrained, instead of the current infcx root item. This makes `Bind` almost always be empty, so we can start forwarding it to queries, allowing us to remove `Bubble` entirely --- compiler/rustc_borrowck/src/consumers.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 5 +- .../src/region_infer/opaque_types.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 4 +- compiler/rustc_hir_typeck/src/inherited.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 6 +- .../rustc_infer/src/infer/opaque_types/mod.rs | 60 +------------------ .../rustc_middle/src/mir/type_foldable.rs | 10 ++++ compiler/rustc_middle/src/traits/mod.rs | 16 +++-- compiler/rustc_middle/src/traits/solve.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 10 ++++ compiler/rustc_middle/src/ty/context.rs | 8 +++ .../error_reporting/type_err_ctxt_ext.rs | 19 ++---- compiler/rustc_ty_utils/src/opaque_types.rs | 12 ++++ compiler/rustc_ty_utils/src/sig_types.rs | 14 ++++- .../generic-associated-types/issue-88595.rs | 1 + .../issue-88595.stderr | 16 ++++- tests/ui/impl-trait/auto-trait-leak.stderr | 6 +- tests/ui/impl-trait/issues/issue-78722-2.rs | 4 +- .../ui/impl-trait/issues/issue-78722-2.stderr | 33 ++++------ tests/ui/lint/issue-99387.rs | 2 +- tests/ui/lint/issue-99387.stderr | 17 ++++-- .../auto-trait-leakage3.stderr | 6 +- .../generic_duplicate_param_use.stderr | 24 ++++---- .../generic_nondefining_use.stderr | 18 +++--- .../hidden_type_mismatch.rs | 2 +- .../hidden_type_mismatch.stderr | 27 ++++++--- .../higher_kinded_params2.rs | 2 +- .../higher_kinded_params2.stderr | 13 ++-- .../higher_kinded_params3.rs | 1 - .../higher_kinded_params3.stderr | 26 +++----- .../implied_bounds_from_types.rs | 1 + .../implied_bounds_from_types.stderr | 17 +++++- .../inference-cycle.stderr | 6 +- .../ui/type-alias-impl-trait/issue-53092-2.rs | 1 + .../issue-53092-2.stderr | 20 +++++-- tests/ui/type-alias-impl-trait/issue-53092.rs | 1 + .../type-alias-impl-trait/issue-53092.stderr | 21 +++++-- tests/ui/type-alias-impl-trait/issue-70121.rs | 2 +- .../type-alias-impl-trait/issue-70121.stderr | 17 ++++-- tests/ui/type-alias-impl-trait/issue-77179.rs | 2 +- .../type-alias-impl-trait/issue-77179.stderr | 36 ++++++----- tests/ui/type-alias-impl-trait/multi-error.rs | 1 + .../type-alias-impl-trait/multi-error.stderr | 11 +++- .../non-defining-method.rs | 1 + .../non-defining-method.stderr | 10 +++- .../type-alias-impl-trait/reveal_local.stderr | 12 +--- 47 files changed, 300 insertions(+), 229 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index a58fe2b744701..31307ef14102e 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -106,7 +106,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(def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, 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 8dcfe014b653e..415ba095a1b24 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -126,10 +126,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let hir_owner = tcx.local_def_id_to_hir_id(def).owner; - - let infcx = - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, 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 12b02c7fcfa1d..3bd4a23faeda5 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -317,7 +317,7 @@ fn check_opaque_type_well_formed<'tcx>( let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(DefiningAnchor::Bind(parent_def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, 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 1b24c2b61fd07..cb739ac48a8b6 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -347,7 +347,7 @@ fn check_opaque_meets_bounds<'tcx>( let infcx = tcx .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor)) .build(); let ocx = ObligationCtxt::new(&infcx); @@ -1558,7 +1558,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(typeck.hir_owner.def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id)) .build(); let mut fulfillment_cx = >::new(&infcx); diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 4ad46845f0ba8..b0950ed280084 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -79,7 +79,7 @@ impl<'tcx> Inherited<'tcx> { let infcx = tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id)) .build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 15cdd6a910e77..323a3c4b984f5 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> { /// /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that /// might come up during inference or typeck. - pub defining_use_anchor: DefiningAnchor, + pub defining_use_anchor: DefiningAnchor<'tcx>, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -605,7 +605,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, + defining_use_anchor: DefiningAnchor<'tcx>, considering_regions: bool, skip_leak_check: bool, /// Whether we are in coherence mode. @@ -636,7 +636,7 @@ 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) -> Self { + pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self { self.defining_use_anchor = defining_use_anchor; self } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 3d6829ba6579f..46ee00247aad5 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -378,28 +378,14 @@ 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 opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id); - let parent_def_id = match self.defining_use_anchor { + let defined_opaque_types = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, DefiningAnchor::Bind(bind) => bind, }; let origin = self.tcx.opaque_type_origin(def_id); - let in_definition_scope = match origin { - // Async `impl Trait` - hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, - // Anonymous `impl Trait` - hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, - // Named `type Foo = impl Bar;` - hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => { - if in_assoc_ty { - self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id) - } else { - may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) - } - } - }; - in_definition_scope.then_some(origin) + + defined_opaque_types.contains(&def_id).then_some(origin) } } @@ -656,43 +642,3 @@ impl<'tcx> InferCtxt<'tcx> { } } } - -/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`. -/// -/// Example: -/// ```ignore UNSOLVED (is this a bug?) -/// # #![feature(type_alias_impl_trait)] -/// pub mod foo { -/// pub mod bar { -/// pub trait Bar { /* ... */ } -/// pub type Baz = impl Bar; -/// -/// # impl Bar for () {} -/// fn f1() -> Baz { /* ... */ } -/// } -/// fn f2() -> bar::Baz { /* ... */ } -/// } -/// ``` -/// -/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), -/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. -/// For the above example, this function returns `true` for `f1` and `false` for `f2`. -fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { - let mut hir_id = tcx.local_def_id_to_hir_id(def_id); - - // Named opaque types can be defined by any siblings or children of siblings. - let scope = tcx.hir().get_defining_scope(opaque_hir_id); - // We walk up the node tree until we hit the root or the scope of the opaque type. - while hir_id != scope && hir_id != hir::CRATE_HIR_ID { - hir_id = tcx.hir().get_parent_item(hir_id).into(); - } - // Syntactically, we are allowed to define the concrete type if: - let res = hir_id == scope; - trace!( - "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.hir_node(hir_id), - tcx.hir_node(opaque_hir_id), - res - ); - res -} diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 93a9bbf64c926..b798f0788007f 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,6 +1,7 @@ //! `TypeFoldable` implementations for MIR types use rustc_ast::InlineAsmTemplatePiece; +use rustc_hir::def_id::LocalDefId; use super::*; @@ -44,6 +45,15 @@ impl<'tcx> TypeFoldable> for &'tcx [Span] { } } +impl<'tcx> TypeFoldable> for &'tcx ty::List { + fn try_fold_with>>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) + } +} + impl<'tcx> TypeFoldable> for &'tcx ty::List> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a6e4702d81950..4113be9f6be77 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}; @@ -1001,10 +1001,10 @@ 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)] -pub enum DefiningAnchor { - /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly - /// replace opaque types in `replace_opaque_types_with_inference_vars`. - Bind(LocalDefId), +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`. + 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 @@ -1018,3 +1018,9 @@ pub enum DefiningAnchor { /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). Error, } + +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/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 95139b50cb89e..dc4cd2034156e 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -114,7 +114,7 @@ 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, + pub anchor: DefiningAnchor<'tcx>, pub predefined_opaques_in_body: PredefinedOpaques<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 69ae05ca820a3..ddbc0bffaedde 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -17,6 +17,7 @@ use crate::traits; use crate::ty::GenericArgsRef; use crate::ty::{self, AdtDef, Ty}; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; @@ -431,6 +432,15 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> RefDecodable<'tcx, D> for ty::List { + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.interner().mk_local_def_ids_from_iter( + (0..len).map::(|_| Decodable::decode(decoder)), + ) + } +} + 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 b08e5df30eff6..c415c06c21b96 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2014,6 +2014,14 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_local_def_ids(clauses) } + pub fn mk_local_def_ids_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: CollectAndApply>, + { + T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs)) + } + pub fn mk_const_list_from_iter(self, iter: I) -> T::Output where I: Iterator, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 71fcc47dba344..ad5b7debad7b4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -32,7 +32,7 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; -use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData}; +use rustc_middle::traits::SignatureMismatchData; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; @@ -3390,19 +3390,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { obligation.cause.span, format!("cannot check whether the hidden type of {name} satisfies auto traits"), ); + + err.note( + "fetching the hidden types of an opaque inside of the defining scope is not supported. \ + You can try moving the opaque type and the item that actually registers a hidden type into a new submodule", + ); err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); - match self.defining_use_anchor { - DefiningAnchor::Bubble | DefiningAnchor::Error => {} - DefiningAnchor::Bind(bind) => { - err.span_note( - self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)), - "this item depends on auto traits of the hidden type, \ - but may also be registering the hidden type. \ - This is not supported right now. \ - You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(), - ); - } - }; self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 3dcc8382289f5..4b706ef955ac4 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -210,12 +210,24 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { self.visit_opaque_ty(alias_ty); } + // Skips type aliases, as they are meant to be transparent. ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => { self.tcx .type_of(alias_ty.def_id) .instantiate(self.tcx, alias_ty.args) .visit_with(self); } + // RPITIT are encoded as projections, not opaque types, make sure to handle these special + // projections independently of the projection handling below. + ty::Alias(ty::Projection, alias_ty) + if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = + self.tcx.opt_rpitit_info(alias_ty.def_id) + && fn_def_id == self.item.into() => + { + let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args); + let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") }; + self.visit_opaque_ty(alias_ty); + } ty::Alias(ty::Projection, alias_ty) => { // This avoids having to do normalization of `Self::AssocTy` by only // supporting the case of a method defining opaque types from assoc types diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 5527d853e3048..72fcc95c3b352 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -23,8 +23,14 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( match kind { // Walk over the signature of the function DefKind::AssocFn | DefKind::Fn => { - let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap(); + // If the type of the item uses `_`, we're gonna error out anyway, but + // typeck (which type_of invokes below), will call back into opaque_types_defined_by + // causing a cycle. So we just bail out in this case. + if hir_sig.output.get_infer_ret_ty().is_some() { + return V::Result::output(); + } + let ty_sig = tcx.fn_sig(item).instantiate_identity(); // Walk over the inputs and outputs manually in order to get good spans for them. try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output())); for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { @@ -39,6 +45,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Walk over the type of the item DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { + // If the type of the item uses `_`, we're gonna error out anyway, but + // typeck (which type_of invokes below), will call back into opaque_types_defined_by + // causing a cycle. So we just bail out in this case. + if ty.is_suggestable_infer_ty() { + return V::Result::output(); + } // Associated types in traits don't necessarily have a type that we can visit try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs index 5a40a61297233..b1fe542a5681f 100644 --- a/tests/ui/generic-associated-types/issue-88595.rs +++ b/tests/ui/generic-associated-types/issue-88595.rs @@ -19,4 +19,5 @@ impl<'a> A<'a> for C { type B<'b> = impl Clone; fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope + //~^ ERROR: non-defining opaque type use in defining scope } diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr index ab75a92400601..87dd7118c06f2 100644 --- a/tests/ui/generic-associated-types/issue-88595.stderr +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -10,5 +10,19 @@ note: for this opaque type LL | type B<'b> = impl Clone; | ^^^^^^^^^^ -error: aborting due to 1 previous error +error: non-defining opaque type use in defining scope + --> $DIR/issue-88595.rs:21:35 + | +LL | fn a(&'a self) -> Self::B<'a> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/issue-88595.rs:18:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +LL | type B<'b> = impl Clone; + | ^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index 3fab766fa235c..cc9939f2d57f9 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -6,16 +6,12 @@ LL | send(cycle1().clone()); | | | required by a bound introduced by this call | + = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule note: opaque type is declared here --> $DIR/auto-trait-leak.rs:11:16 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ -note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule - --> $DIR/auto-trait-leak.rs:17:4 - | -LL | fn cycle2() -> impl Clone { - | ^^^^^^ note: required by a bound in `send` --> $DIR/auto-trait-leak.rs:4:12 | diff --git a/tests/ui/impl-trait/issues/issue-78722-2.rs b/tests/ui/impl-trait/issues/issue-78722-2.rs index 26181b612ed25..e811620c03bad 100644 --- a/tests/ui/impl-trait/issues/issue-78722-2.rs +++ b/tests/ui/impl-trait/issues/issue-78722-2.rs @@ -12,9 +12,9 @@ struct Bug { //~^ ERROR future that resolves to `u8`, but it resolves to `()` async {} } + // FIXME(type_alias_impl_trait): inform the user about why `F` is not available here. let f: F = async { 1 }; - //~^ ERROR item constrains opaque type that is not in its signature - //~| ERROR `async` blocks are not allowed in constants + //~^ ERROR mismatched types 1 }], } diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr index c402ce864c74c..91dad1b5e673d 100644 --- a/tests/ui/impl-trait/issues/issue-78722-2.stderr +++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr @@ -4,30 +4,21 @@ error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:21}` to be LL | fn concrete_use() -> F { | ^ expected `()`, found `u8` -error: item constrains opaque type that is not in its signature - --> $DIR/issue-78722-2.rs:15:20 +error[E0308]: mismatched types + --> $DIR/issue-78722-2.rs:16:20 | +LL | type F = impl core::future::Future; + | -------------------------------------- the expected future +... LL | let f: F = async { 1 }; - | ^^^^^^^^^^^ + | - ^^^^^^^^^^^ expected future, found `async` block + | | + | expected due to this | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types - --> $DIR/issue-78722-2.rs:15:20 - | -LL | let f: F = async { 1 }; - | ^^^^^^^^^^^ - -error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722-2.rs:15:20 - | -LL | let f: F = async { 1 }; - | ^^^^^^^^^^^ - | - = note: see issue #85368 for more information - = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: expected opaque type `F` + found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:31}` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0658. +Some errors have detailed explanations: E0271, E0308. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs index 571d4194fe78f..6f08223945640 100644 --- a/tests/ui/lint/issue-99387.rs +++ b/tests/ui/lint/issue-99387.rs @@ -19,8 +19,8 @@ impl<'a> Tr for &'a () { } pub fn ohno<'a>() -> <&'a () as Tr>::Item { - //~^ ERROR item constrains opaque type that is not in its signature None.into_iter() + //~^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr index 0005e55324f7d..4eee4f3639297 100644 --- a/tests/ui/lint/issue-99387.stderr +++ b/tests/ui/lint/issue-99387.stderr @@ -1,11 +1,17 @@ -error: item constrains opaque type that is not in its signature - --> $DIR/issue-99387.rs:21:22 +error[E0308]: mismatched types + --> $DIR/issue-99387.rs:22:5 | +LL | pub type Successors<'a> = impl Iterator; + | ---------------------------- the expected opaque type +... LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { - | ^^^^^^^^^^^^^^^^^^^^ + | -------------------- expected `Successors<'a>` because of return type +LL | None.into_iter() + | ^^^^^^^^^^^^^^^^ expected opaque type, found `IntoIter<_>` | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types + = note: expected opaque type `Successors<'a>` + found struct `std::option::IntoIter<_>` +note: this item must have the opaque type in its signature in order to be able to register hidden types --> $DIR/issue-99387.rs:21:8 | LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { @@ -13,3 +19,4 @@ LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index f6f754557991f..6bdc76aab4503 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -6,16 +6,12 @@ LL | is_send(foo()); | | | required by a bound introduced by this call | + = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule note: opaque type is declared here --> $DIR/auto-trait-leakage3.rs:7:20 | LL | pub type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ -note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule - --> $DIR/auto-trait-leakage3.rs:12:12 - | -LL | pub fn bar() { - | ^^^ note: required by a bound in `is_send` --> $DIR/auto-trait-leakage3.rs:17:19 | diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 495308a6cace1..73570de53266f 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -34,18 +34,6 @@ note: for this opaque type LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^^^^^^^^^ -error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:29:5 - | -LL | t - | ^ - | -note: lifetime used multiple times - --> $DIR/generic_duplicate_param_use.rs:17:19 - | -LL | type TwoLifetimes<'a, 'b> = impl Debug; - | ^^ ^^ - error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:33:50 | @@ -58,6 +46,18 @@ note: for this opaque type LL | type TwoConsts = impl Debug; | ^^^^^^^^^^ +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:29:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_param_use.rs:17:19 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug; + | ^^ ^^ + error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:35:5 | diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr index e3b7b1a76b09d..bd68b4e3ea469 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -31,15 +31,6 @@ note: for this opaque type LL | type OneLifetime<'a> = impl Debug; | ^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'static` - --> $DIR/generic_nondefining_use.rs:23:5 - | -LL | type OneLifetime<'a> = impl Debug; - | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type -... -LL | 6u32 - | ^^^^ - error[E0792]: non-defining opaque type use in defining scope --> $DIR/generic_nondefining_use.rs:27:24 | @@ -52,6 +43,15 @@ note: for this opaque type LL | type OneConst = impl Debug; | ^^^^^^^^^^ +error[E0792]: expected generic lifetime parameter, found `'static` + --> $DIR/generic_nondefining_use.rs:23:5 + | +LL | type OneLifetime<'a> = impl Debug; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | 6u32 + | ^^^^ + error[E0792]: expected generic constant parameter, found `123` --> $DIR/generic_nondefining_use.rs:29:5 | diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs index 12ce6b14e31da..5b5acb31812f3 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs @@ -9,7 +9,6 @@ mod sus { use super::*; pub type Sep = impl Sized + std::fmt::Display; - //~^ ERROR: concrete type differs from previous defining opaque type use pub fn mk_sep() -> Sep { String::from("hello") } @@ -42,6 +41,7 @@ mod sus { (): Proj, { Bar { inner: 1i32, _marker: () } + //~^ ERROR type mismatch } } diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr index 5a6998f41658e..21d9ed9336666 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr @@ -1,14 +1,27 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/hidden_type_mismatch.rs:11:20 +error[E0271]: type mismatch resolving `<() as Proj>::Assoc == i32` + --> $DIR/hidden_type_mismatch.rs:43:9 | LL | pub type Sep = impl Sized + std::fmt::Display; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `String` + | ------------------------------ the expected opaque type +... +LL | Bar { inner: 1i32, _marker: () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Proj>::Assoc == i32` | -note: previous use here - --> $DIR/hidden_type_mismatch.rs:37:21 +note: expected this to be `Sep` + --> $DIR/hidden_type_mismatch.rs:20:22 | -LL | pub type Tait = impl Copy + From> + Into>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Assoc = sus::Sep; + | ^^^^^^^^ + = note: expected opaque type `Sep` + found type `i32` +note: required for `Bar<()>` to implement `Copy` + --> $DIR/hidden_type_mismatch.rs:32:39 + | +LL | impl + Copy> Copy for Bar {} + | ----------- ^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs index 1022e5c4ecedb..19c6099135d83 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs @@ -24,7 +24,7 @@ type Successors<'a> = impl std::fmt::Debug + 'a; impl Terminator { fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { f = g; - //~^ ERROR item constrains opaque type that is not in its signature + //~^ ERROR mismatched types } } diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr index e037dede2e0f6..790e7fe858037 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr @@ -1,11 +1,15 @@ -error: item constrains opaque type that is not in its signature +error[E0308]: mismatched types --> $DIR/higher_kinded_params2.rs:26:13 | +LL | type Tait = impl std::fmt::Debug; + | -------------------- the expected opaque type +... LL | f = g; - | ^ + | ^ expected fn pointer, found fn item | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types + = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait` + found fn item `for<'a> fn(&'a ()) -> String {g}` +note: this item must have the opaque type in its signature in order to be able to register hidden types --> $DIR/higher_kinded_params2.rs:25:8 | LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { @@ -13,3 +17,4 @@ LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> S error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs index e0bb1e2d02fc3..3845cde29fa55 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs @@ -25,7 +25,6 @@ impl Terminator { fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { f = g; //~^ ERROR mismatched types - //~| ERROR item constrains opaque type that is not in its signature } } diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr index 14372d8f3e64d..41a3f9ce26820 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr @@ -1,28 +1,20 @@ -error: item constrains opaque type that is not in its signature - --> $DIR/higher_kinded_params3.rs:26:13 - | -LL | f = g; - | ^ - | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types - --> $DIR/higher_kinded_params3.rs:25:8 - | -LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { - | ^^^^^^^^^^ - error[E0308]: mismatched types - --> $DIR/higher_kinded_params3.rs:26:9 + --> $DIR/higher_kinded_params3.rs:26:13 | LL | type Tait<'a> = impl std::fmt::Debug + 'a; | ------------------------- the expected opaque type ... LL | f = g; - | ^^^^^ one type is more general than the other + | ^ expected fn pointer, found fn item | = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>` - found fn pointer `for<'a> fn(&'a ()) -> &'a ()` + found fn item `for<'a> fn(&'a ()) -> &'a () {g}` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/higher_kinded_params3.rs:25:8 + | +LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { + | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs index 8023cd24f0bf6..239fcc6a5e6f3 100644 --- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs @@ -12,6 +12,7 @@ impl<'a> Convert<'a> for () { type Witness = WithLifetime<&'a ()>; fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + //~^ ERROR non-defining opaque type use // compiler used to think it gets to assume 'a: 'b here because // of the `&'b WithLifetime<&'a ()>` argument x diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr index 5967a9468302c..23dbf0e8f60c3 100644 --- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -1,5 +1,17 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/implied_bounds_from_types.rs:14:39 + | +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ argument `&'a ()` is not a generic parameter + | +note: for this opaque type + --> $DIR/implied_bounds_from_types.rs:3:24 + | +LL | type WithLifetime = impl Equals; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: lifetime may not live long enough - --> $DIR/implied_bounds_from_types.rs:17:9 + --> $DIR/implied_bounds_from_types.rs:18:9 | LL | impl<'a> Convert<'a> for () { | -- lifetime `'a` defined here @@ -12,5 +24,6 @@ LL | x | = help: consider adding the following bound: `'a: 'b` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index fd7488fa2601e..8b809ba014d96 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -6,16 +6,12 @@ LL | is_send(foo()); | | | required by a bound introduced by this call | + = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule note: opaque type is declared here --> $DIR/inference-cycle.rs:5:20 | LL | pub type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ -note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule - --> $DIR/inference-cycle.rs:11:12 - | -LL | pub fn bar() { - | ^^^ note: required by a bound in `is_send` --> $DIR/inference-cycle.rs:21:19 | diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs index 057930f0c1ce7..61b23a3a93322 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -4,6 +4,7 @@ type Bug = impl Fn(T) -> U + Copy; //~ ERROR cycle detected const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; +//~^ ERROR: non-defining opaque type use fn make_bug>() -> Bug { |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index e805a71ea6f30..c2da5fc265cc2 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -1,3 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/issue-53092-2.rs:6:18 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^ argument `u8` is not a generic parameter + | +note: for this opaque type + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` --> $DIR/issue-53092-2.rs:4:18 | @@ -25,13 +37,13 @@ LL | type Bug = impl Fn(T) -> U + Copy; = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0277]: the trait bound `U: From` is not satisfied - --> $DIR/issue-53092-2.rs:9:5 + --> $DIR/issue-53092-2.rs:10:5 | LL | |x| x.into() | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` | note: required by a bound in `make_bug` - --> $DIR/issue-53092-2.rs:8:19 + --> $DIR/issue-53092-2.rs:9:19 | LL | fn make_bug>() -> Bug { | ^^^^^^^ required by this bound in `make_bug` @@ -40,7 +52,7 @@ help: consider restricting type parameter `U` LL | type Bug> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0391. +Some errors have detailed explanations: E0277, E0391, E0792. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092.rs b/tests/ui/type-alias-impl-trait/issue-53092.rs index 1be5b46d6df68..34bab02608852 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092.rs @@ -9,6 +9,7 @@ union Moo { } const CONST_BUG: Bug = unsafe { Moo { y: () }.x }; +//~^ ERROR non-defining opaque type use fn make_bug>() -> Bug { |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr index 8605a0981933c..0c4cacd665503 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -1,11 +1,23 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/issue-53092.rs:11:18 + | +LL | const CONST_BUG: Bug = unsafe { Moo { y: () }.x }; + | ^^^^^^^^^^^ argument `u8` is not a generic parameter + | +note: for this opaque type + --> $DIR/issue-53092.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `U: From` is not satisfied - --> $DIR/issue-53092.rs:14:5 + --> $DIR/issue-53092.rs:15:5 | LL | |x| x.into() | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` | note: required by a bound in `make_bug` - --> $DIR/issue-53092.rs:13:19 + --> $DIR/issue-53092.rs:14:19 | LL | fn make_bug>() -> Bug { | ^^^^^^^ required by this bound in `make_bug` @@ -14,6 +26,7 @@ help: consider restricting type parameter `U` LL | type Bug> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0792. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs index bfd8d8872e37f..b90bd312a0ba7 100644 --- a/tests/ui/type-alias-impl-trait/issue-70121.rs +++ b/tests/ui/type-alias-impl-trait/issue-70121.rs @@ -15,8 +15,8 @@ impl<'a> Tr for &'a () { } pub fn kazusa<'a>() -> <&'a () as Tr>::Item { - //~^ ERROR item constrains opaque type that is not in its signature None.into_iter() + //~^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr index d6ab26e30daf6..ed2eb17fbead4 100644 --- a/tests/ui/type-alias-impl-trait/issue-70121.stderr +++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr @@ -1,11 +1,17 @@ -error: item constrains opaque type that is not in its signature - --> $DIR/issue-70121.rs:17:24 +error[E0308]: mismatched types + --> $DIR/issue-70121.rs:18:5 | +LL | pub type Successors<'a> = impl Iterator; + | ---------------------------- the expected opaque type +... LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { - | ^^^^^^^^^^^^^^^^^^^^ + | -------------------- expected `Successors<'a>` because of return type +LL | None.into_iter() + | ^^^^^^^^^^^^^^^^ expected opaque type, found `IntoIter<_>` | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types + = note: expected opaque type `Successors<'a>` + found struct `std::option::IntoIter<_>` +note: this item must have the opaque type in its signature in order to be able to register hidden types --> $DIR/issue-70121.rs:17:8 | LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { @@ -13,3 +19,4 @@ LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 2d9345a3e5e8e..1dc74c6b5fea2 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -7,7 +7,7 @@ type Pointer = impl std::ops::Deref; fn test() -> Pointer<_> { //~^ ERROR: the placeholder `_` is not allowed within types Box::new(1) - //~^ ERROR: expected generic type parameter, found `i32` + //~^ ERROR: mismatched types } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index ebd78e5b7a54f..85a943c26e2d5 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -1,11 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/issue-77179.rs:9:5 + | +LL | type Pointer = impl std::ops::Deref; + | -------------------------------- the expected opaque type +LL | +LL | fn test() -> Pointer<_> { + | ---------- expected `Pointer<_>` because of return type +LL | +LL | Box::new(1) + | ^^^^^^^^^^^ expected opaque type, found `Box<{integer}>` + | + = note: expected opaque type `Pointer<_>` + found struct `Box<{integer}>` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/issue-77179.rs:7:4 + | +LL | fn test() -> Pointer<_> { + | ^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-77179.rs:7:22 | LL | fn test() -> Pointer<_> { - | --------^- - | | | - | | not allowed in type signatures - | help: replace with the correct return type: `Pointer` + | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-77179.rs:18:25 @@ -16,16 +33,7 @@ LL | fn bar() -> Pointer<_>; | not allowed in type signatures | help: use type parameters instead: `T` -error[E0792]: expected generic type parameter, found `i32` - --> $DIR/issue-77179.rs:9:5 - | -LL | type Pointer = impl std::ops::Deref; - | - this generic parameter must be used with a generic type parameter -... -LL | Box::new(1) - | ^^^^^^^^^^^ - error: aborting due to 3 previous errors -Some errors have detailed explanations: E0121, E0792. +Some errors have detailed explanations: E0121, E0308. For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs index b5ff06572d06e..cb4ad4dc63372 100644 --- a/tests/ui/type-alias-impl-trait/multi-error.rs +++ b/tests/ui/type-alias-impl-trait/multi-error.rs @@ -17,6 +17,7 @@ impl Foo for () { fn foo() -> (Self::Bar, Self::Baz) { //~^ ERROR non-defining opaque type use ((), ()) + //~^ ERROR expected generic type parameter } } diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr index b0e6d13b0e1f0..761f01b32acf4 100644 --- a/tests/ui/type-alias-impl-trait/multi-error.stderr +++ b/tests/ui/type-alias-impl-trait/multi-error.stderr @@ -10,6 +10,15 @@ note: for this opaque type LL | type Bar = impl Sized; | ^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0792]: expected generic type parameter, found `u32` + --> $DIR/multi-error.rs:19:9 + | +LL | type Bar = impl Sized; + | - this generic parameter must be used with a generic type parameter +... +LL | ((), ()) + | ^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.rs b/tests/ui/type-alias-impl-trait/non-defining-method.rs index 2f4a7052f7221..8551806b3cb77 100644 --- a/tests/ui/type-alias-impl-trait/non-defining-method.rs +++ b/tests/ui/type-alias-impl-trait/non-defining-method.rs @@ -15,6 +15,7 @@ impl Foo for () { type Bar = impl Sized; fn foo() -> Self::Bar {} //~^ ERROR non-defining opaque type use + //~| ERROR expected generic type parameter, found `u32` fn bar() -> Self::Bar {} } diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr index 2ba4c90a1c431..49a393ca745bb 100644 --- a/tests/ui/type-alias-impl-trait/non-defining-method.stderr +++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr @@ -10,6 +10,14 @@ note: for this opaque type LL | type Bar = impl Sized; | ^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0792]: expected generic type parameter, found `u32` + --> $DIR/non-defining-method.rs:16:32 + | +LL | type Bar = impl Sized; + | - this generic parameter must be used with a generic type parameter +LL | fn foo() -> Self::Bar {} + | ^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr index 796e2d011dc6b..e1b320cc38e31 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -4,16 +4,12 @@ error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque LL | is_send::(); | ^^^ | + = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule note: opaque type is declared here --> $DIR/reveal_local.rs:5:12 | LL | type Foo = impl Debug; | ^^^^^^^^^^ -note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule - --> $DIR/reveal_local.rs:9:4 - | -LL | fn not_good() { - | ^^^^^^^^ note: required by a bound in `is_send` --> $DIR/reveal_local.rs:7:15 | @@ -26,16 +22,12 @@ error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque LL | is_send::(); | ^^^ | + = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule note: opaque type is declared here --> $DIR/reveal_local.rs:5:12 | LL | type Foo = impl Debug; | ^^^^^^^^^^ -note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule - --> $DIR/reveal_local.rs:16:4 - | -LL | fn not_gooder() -> Foo { - | ^^^^^^^^^^ note: required by a bound in `is_send` --> $DIR/reveal_local.rs:7:15 | From 7348dd1950ea0f14fcf6f521a85dd27796ef386a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 09:08:20 +0000 Subject: [PATCH 2/6] Eliminate `DefiningAnchor::Error`, it is indistinguishable from `DefiningAnchor::Bind` with an empty list --- compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 7 +++---- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 5 +---- compiler/rustc_middle/src/traits/mod.rs | 8 ++++---- compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs | 7 ++----- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 3bd4a23faeda5..8a17223303718 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -311,7 +311,7 @@ fn check_opaque_type_well_formed<'tcx>( parent_def_id = tcx.local_parent(parent_def_id); } - // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Error` + // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])` // and prepopulate this `InferCtxt` with known opaque values, rather than // using the `Bind` anchor here. For now it's fine. let infcx = tcx diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 323a3c4b984f5..89e4e88b3df24 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -242,7 +242,8 @@ pub struct InferCtxt<'tcx> { /// 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. /// - /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that + /// 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>, @@ -620,7 +621,7 @@ impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, - defining_use_anchor: DefiningAnchor::Error, + defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()), considering_regions: true, skip_leak_check: false, intercrate: false, @@ -1208,13 +1209,11 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self), ret)] pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error); std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types) } #[instrument(level = "debug", skip(self), ret)] pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error); self.inner.borrow().opaque_type_storage.opaque_types.clone() } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 46ee00247aad5..a6f8115c27e2d 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -150,9 +150,6 @@ impl<'tcx> InferCtxt<'tcx> { } } DefiningAnchor::Bubble => {} - DefiningAnchor::Error => { - 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 @@ -379,7 +376,7 @@ 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 | DefiningAnchor::Error => return None, + DefiningAnchor::Bubble => return None, DefiningAnchor::Bind(bind) => bind, }; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 4113be9f6be77..aea5865335124 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -1004,6 +1004,10 @@ pub enum CodegenObligationError { 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), /// 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 @@ -1013,10 +1017,6 @@ pub enum DefiningAnchor<'tcx> { /// 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, - /// 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). - Error, } impl<'tcx> DefiningAnchor<'tcx> { 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 22f52c273625f..3b858cb449fa1 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -16,7 +16,7 @@ use rustc_middle::traits::solve::{ CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, PredefinedOpaques, PredefinedOpaquesData, QueryResult, }; -use rustc_middle::traits::{specialization_graph, DefiningAnchor}; +use rustc_middle::traits::specialization_graph; use rustc_middle::ty::{ self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, @@ -258,10 +258,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // instead of taking them. This would cause an ICE here, since we have // assertions against dropping an `InferCtxt` without taking opaques. // FIXME: Once we remove support for the old impl we can remove this. - if input.anchor != DefiningAnchor::Error { - // This seems ok, but fragile. - let _ = infcx.take_opaque_types(); - } + let _ = infcx.take_opaque_types(); result } From b0328c20ce75a56879bda08235242c21c1a451a1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 11 Mar 2024 17:51:10 +0100 Subject: [PATCH 3/6] update comment for RPITIT projections --- compiler/rustc_ty_utils/src/opaque_types.rs | 37 ++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4b706ef955ac4..4a1064b29f6f9 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { self.span = old; } - fn parent_trait_ref(&self) -> Option> { + fn parent_impl_trait_ref(&self) -> Option> { let parent = self.parent()?; if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()) @@ -217,26 +217,15 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { .instantiate(self.tcx, alias_ty.args) .visit_with(self); } - // RPITIT are encoded as projections, not opaque types, make sure to handle these special - // projections independently of the projection handling below. - ty::Alias(ty::Projection, alias_ty) - if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = - self.tcx.opt_rpitit_info(alias_ty.def_id) - && fn_def_id == self.item.into() => - { - let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args); - let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") }; - self.visit_opaque_ty(alias_ty); - } ty::Alias(ty::Projection, alias_ty) => { // This avoids having to do normalization of `Self::AssocTy` by only // supporting the case of a method defining opaque types from assoc types // in the same impl block. - if let Some(parent_trait_ref) = self.parent_trait_ref() { + if let Some(impl_trait_ref) = self.parent_impl_trait_ref() { // If the trait ref of the associated item and the impl differs, // then we can't use the impl's identity args below, so // just skip. - if alias_ty.trait_ref(self.tcx) == parent_trait_ref { + if alias_ty.trait_ref(self.tcx) == impl_trait_ref { let parent = self.parent().expect("we should have a parent here"); for &assoc in self.tcx.associated_items(parent).in_definition_order() { @@ -253,7 +242,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { let impl_args = alias_ty.args.rebase_onto( self.tcx, - parent_trait_ref.def_id, + impl_trait_ref.def_id, ty::GenericArgs::identity_for_item(self.tcx, parent), ); @@ -271,6 +260,24 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } } } + } else if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = + self.tcx.opt_rpitit_info(alias_ty.def_id) + && fn_def_id == self.item.into() + { + // RPITIT in trait definitions get desugared to an associated type. For + // default methods we also create an opaque type this associated type + // normalizes to. The associated type is only known to normalize to the + // opaque if it is fully concrete. There could otherwise be an impl + // overwriting the default method. + // + // However, we have to be able to normalize the associated type while inside + // of the default method. This is normally handled by adding an unchecked + // `Projection(::synthetic_assoc_ty, trait_def::opaque)` + // assumption to the `param_env` of the default method. We also separately + // rely on that assumption here. + let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args); + let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") }; + self.visit_opaque_ty(alias_ty); } } ty::Adt(def, _) if def.did().is_local() => { From fe240e86b9eb378f1f5ac2d85c16d4bcadf69fdb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Mar 2024 10:21:27 +0000 Subject: [PATCH 4/6] Pass list of defineable opaque types into canonical queries --- .../src/region_infer/opaque_types.rs | 11 +++++++++ .../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 | 10 ++++---- 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 +-------- .../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 ++++----- 28 files changed, 88 insertions(+), 129 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 8a17223303718..2be455f35695d 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -146,6 +146,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { opaque_type_key, universal_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. + if let ty::Alias(ty::Opaque, alias_ty) = universal_concrete_type.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 89e4e88b3df24..0201f7df26a35 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -234,13 +234,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 @@ -392,6 +386,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. @@ -670,14 +668,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_with_fresh_inference_vars(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 a6f8115c27e2d..13ec261969309 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -149,7 +149,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 @@ -376,7 +375,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 7b65c11bc3c82..333da403ab42a 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 8d88488e1675d..3c79bbe93a272 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -340,10 +340,10 @@ macro_rules! define_callbacks { <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> >::Cache; - // Ensure that keys grow no larger than 64 bytes + // Ensure that keys grow no larger than 72 bytes #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 64 { + if mem::size_of::>() > 72 { panic!("{}", concat!( "the query `", stringify!($name), @@ -354,10 +354,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(target_arch = "x86_64", 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 aea5865335124..becbf868d9257 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -1001,6 +1001,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`. @@ -1009,14 +1010,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 dc4cd2034156e..0e4412c9ba527 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 c415c06c21b96..93b94d12099e2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -81,6 +81,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 95b3006666202..6875993617b3a 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 f694dd0070363..e5ff8c899a13e 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; @@ -133,9 +133,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 251b0a193f1bb..b6c1a24a9b135 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -65,7 +65,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 3b858cb449fa1..5111bb6e416f4 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -226,7 +226,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 0bf28f520a4d2..ddb9b9979113e 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -320,5 +320,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 ad18ef249842f..85b32be80606f 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 } } } @@ -100,6 +101,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, }) } } 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 373540de05e0e..e57204777843c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,6 +10,7 @@ use crate::{ pub trait Interner: Sized { type DefId: Copy + Debug + Hash + Ord; + type DefiningAnchor: Copy + Debug + Hash + Default; type AdtDef: Copy + Debug + Hash + Ord; 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/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 069292239bc89..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:31:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - | - - --> $DIR/rpit_tait_equality_in_canonical_query.rs:31: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 88a8f6e11a531..42b7bb7f83ecf 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 @@ -7,17 +7,7 @@ //@ revisions: current next //@[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 e09cde6da05b64e71757381e8a472dbccaf0ae05 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 10:29:11 +0000 Subject: [PATCH 5/6] 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 +- compiler/rustc_hir_typeck/src/inherited.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 | 12 +-- 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, 101 insertions(+), 132 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 415ba095a1b24..78e092d3c2308 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 2be455f35695d..33082b9bb8048 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::InferCtxt; use rustc_infer::infer::TyCtxtInferExt as _; 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}; @@ -322,13 +321,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 cb739ac48a8b6..fac311be279de 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 { @@ -1558,7 +1555,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/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index b0950ed280084..e22e14a0a9e57 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.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; @@ -76,11 +75,7 @@ impl<'tcx> Inherited<'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)); Inherited { 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 0201f7df26a35..403d2eb299a18 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}; @@ -235,11 +235,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 @@ -387,8 +383,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 } } @@ -604,7 +600,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. @@ -619,7 +615,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, @@ -635,8 +631,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 } @@ -675,7 +679,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_with_fresh_inference_vars(span, canonical); (infcx, value, args) } @@ -683,7 +687,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, @@ -691,7 +695,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 13ec261969309..d95a34d17e00a 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; @@ -109,47 +109,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 @@ -374,13 +371,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 333da403ab42a..aec26ec651d79 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 becbf868d9257..d21ee8ca62816 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}; @@ -994,32 +994,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 ddbc0bffaedde..eff9cc2f8fb1b 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -441,6 +441,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 93b94d12099e2..5422934201c1f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -81,7 +81,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 336c2dce1141c..615f34bc6207e 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -39,6 +39,12 @@ pub struct List { opaque: OpaqueListContents, } +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 6875993617b3a..0269801869098 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 ddb9b9979113e..ffe109720dddd 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -320,6 +320,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 85b32be80606f..b2701ae744e09 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 } } } @@ -101,7 +101,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, }) } } 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 e57204777843c..9d01c9243c02a 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,7 +10,7 @@ use crate::{ pub trait Interner: Sized { type DefId: Copy + Debug + Hash + Ord; - type DefiningAnchor: Copy + Debug + Hash + Default; + type DefiningOpaqueTypes: Copy + Debug + Hash + Default; type AdtDef: Copy + Debug + Hash + Ord; type GenericArgs: Copy From cb7c75b2f5f847109ef60591aa609fdbe66e8450 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 12:27:58 +0000 Subject: [PATCH 6/6] 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 3c79bbe93a272..bdd399578dcdb 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -340,7 +340,8 @@ macro_rules! define_callbacks { <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> >::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(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { if mem::size_of::>() > 72 { @@ -354,10 +355,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(target_arch = "x86_64", 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 5422934201c1f..fbd0e46b7e87a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -162,6 +162,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)>>, } @@ -189,6 +190,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(), } } @@ -1773,6 +1775,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)), ); @@ -2023,6 +2026,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,