diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_borrowck/src/consumers.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/lib.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 102 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/type_check/mod.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/mod.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/opaque_types.rs | 87 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/codegen.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/check.rs | 84 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/compare_method.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/op.rs | 17 |
15 files changed, 228 insertions, 169 deletions
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 97daad201d9..efc17a173f4 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexVec; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::mir::Body; use rustc_middle::ty::{self, TyCtxt}; @@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>( def: ty::WithOptConstParam<LocalDefId>, ) -> BodyWithBorrowckFacts<'tcx> { let (input_body, promoted) = tcx.mir_promoted(def); - tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| { + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 29f47200b80..9dfefe4d236 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -24,7 +24,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::ChunkedBitSet; use rustc_index::vec::IndexVec; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::{ traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents, @@ -130,11 +130,14 @@ fn mir_borrowck<'tcx>( debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; - let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| { - let input_body: &Body<'_> = &input_body.borrow(); - let promoted: &IndexVec<_, _> = &promoted.borrow(); - do_mir_borrowck(&infcx, input_body, promoted, false).0 - }); + let opt_closure_req = tcx + .infer_ctxt() + .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner)) + .enter(|infcx| { + let input_body: &Body<'_> = &input_body.borrow(); + let promoted: &IndexVec<_, _> = &promoted.borrow(); + do_mir_borrowck(&infcx, input_body, promoted, false).0 + }); debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index de9da845729..407bbf48813 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -3,8 +3,8 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::LocalDefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; -use rustc_infer::infer::InferCtxt; use rustc_infer::infer::TyCtxtInferExt as _; +use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; @@ -269,59 +269,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. let param_env = self.tcx.param_env(def_id); let body_id = self.tcx.local_def_id_to_hir_id(def_id); - self.tcx.infer_ctxt().enter(move |infcx| { - // Require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = - ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) - .to_predicate(infcx.tcx); - let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); - - // Require that the hidden type actually fulfills all the bounds of the opaque type, even without - // the bounds that the function supplies. - match infcx.register_hidden_type( - OpaqueTypeKey { def_id, substs: id_substs }, - ObligationCause::misc(instantiated_ty.span, body_id), - param_env, - definition_ty, - origin, - ) { - Ok(infer_ok) => { - for obligation in infer_ok.obligations { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); + // HACK This bubble is required for this tests to pass: + // type-alias-impl-trait/issue-67844-nested-opaque.rs + self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter( + move |infcx| { + // Require the hidden type to be well-formed with only the generics of the opaque type. + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the + // hidden type is well formed even without those bounds. + let predicate = + ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) + .to_predicate(infcx.tcx); + let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); + + // Require that the hidden type actually fulfills all the bounds of the opaque type, even without + // the bounds that the function supplies. + match infcx.register_hidden_type( + OpaqueTypeKey { def_id, substs: id_substs }, + ObligationCause::misc(instantiated_ty.span, body_id), + param_env, + definition_ty, + origin, + ) { + Ok(infer_ok) => { + for obligation in infer_ok.obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } + } + Err(err) => { + infcx + .report_mismatched_types( + &ObligationCause::misc(instantiated_ty.span, body_id), + self.tcx.mk_opaque(def_id.to_def_id(), id_substs), + definition_ty, + err, + ) + .emit(); } } - Err(err) => { - infcx - .report_mismatched_types( - &ObligationCause::misc(instantiated_ty.span, body_id), - self.tcx.mk_opaque(def_id.to_def_id(), id_substs), - definition_ty, - err, - ) - .emit(); - } - } - fulfillment_cx.register_predicate_obligation( - &infcx, - Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), - ); + fulfillment_cx.register_predicate_obligation( + &infcx, + Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), + ); - // Check that all obligations are satisfied by the implementation's - // version. - let errors = fulfillment_cx.select_all_or_error(&infcx); + // Check that all obligations are satisfied by the implementation's + // version. + let errors = fulfillment_cx.select_all_or_error(&infcx); - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + // This is still required for many(half of the tests in ui/type-alias-impl-trait) + // tests to pass + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - if errors.is_empty() { - definition_ty - } else { - infcx.report_fulfillment_errors(&errors, None, false); - self.tcx.ty_error() - } - }) + if errors.is_empty() { + definition_ty + } else { + infcx.report_fulfillment_errors(&errors, None, false); + self.tcx.ty_error() + } + }, + ) } else { definition_ty } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cf2140097e6..eb9df281e7d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::{ InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, }; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind; @@ -224,6 +225,26 @@ pub(crate) fn type_check<'mir, 'tcx>( ) .unwrap(); let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); + // Check that RPITs are only constrained in their outermost + // function, otherwise report a mismatched types error. + if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent) + = infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span) + && parent.to_def_id() != body.source.def_id() + { + infcx + .report_mismatched_types( + &ObligationCause::misc( + hidden_type.span, + infcx.tcx.hir().local_def_id_to_hir_id( + body.source.def_id().expect_local(), + ), + ), + infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs), + hidden_type.ty, + ty::error::TypeError::Mismatch, + ) + .emit(); + } trace!( "finalized opaque type {:?} to {:#?}", opaque_type_key, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 076b627ca79..735017aa5a8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -727,16 +727,8 @@ impl<'a> TraitDef<'a> { let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived)); let opt_trait_ref = Some(trait_ref); - let unused_qual = { - let word = rustc_ast::attr::mk_nested_word_item(Ident::new( - sym::unused_qualifications, - self.span, - )); - let list = rustc_ast::attr::mk_list_item(Ident::new(sym::allow, self.span), vec![word]); - cx.attribute(list) - }; - let mut a = vec![attr, unused_qual]; + let mut a = vec![attr]; a.extend(self.attributes.iter().cloned()); cx.item( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b3dc2e586d2..0e44d4e7c97 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -239,17 +239,31 @@ impl<'tcx> InferCtxtInner<'tcx> { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum DefiningAnchor { + /// `DefId` of the item. + Bind(LocalDefId), + /// When opaque types are not resolved, we `Bubble` up, meaning + /// return the opaque/hidden type pair from query, for caller of query to handle it. + Bubble, + /// Used to catch type mismatch errors when handling opaque types. + Error, +} + pub struct InferCtxt<'a, '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 `None`, we can't resolve opaque types here and need to bubble up + /// 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. - pub defining_use_anchor: Option<LocalDefId>, + /// + /// It is 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, /// During type-checking/inference of a body, `in_progress_typeck_results` /// contains a reference to the typeck results being built up, which are @@ -526,7 +540,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> { pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>, - defining_use_anchor: Option<LocalDefId>, + defining_use_anchor: DefiningAnchor, } pub trait TyCtxtInferExt<'tcx> { @@ -535,7 +549,11 @@ pub trait TyCtxtInferExt<'tcx> { impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None } + InferCtxtBuilder { + tcx: self, + defining_use_anchor: DefiningAnchor::Error, + fresh_typeck_results: None, + } } } @@ -545,7 +563,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// Will also change the scope for opaque type defining use checks to the given owner. pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self { self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner))); - self.with_opaque_type_inference(table_owner) + self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner)) } /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, @@ -554,8 +572,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// It is only meant to be called in two places, for typeck /// (via `with_fresh_in_progress_typeck_results`) and for the inference context used /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self { - self.defining_use_anchor = Some(defining_use_anchor); + pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self { + self.defining_use_anchor = defining_use_anchor; self } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 4ee9c4eeda4..7b0ff9552a3 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,4 +1,4 @@ -use crate::infer::{InferCtxt, InferOk}; +use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; use hir::def_id::{DefId, LocalDefId}; use hir::{HirId, OpaqueTyOrigin}; @@ -101,44 +101,46 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Opaque(def_id, substs) if def_id.is_local() => { let def_id = def_id.expect_local(); - let origin = if self.defining_use_anchor.is_some() { - // 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` - // } - // ``` - self.opaque_type_origin(def_id, cause.span)? - } else { - self.opaque_ty_origin_unchecked(def_id, cause.span) + let origin = 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` + // } + // ``` + self.opaque_type_origin(def_id, cause.span)? + } + DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span), + DefiningAnchor::Error => return None, }; if let ty::Opaque(did2, _) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't @@ -407,7 +409,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(skip(self), level = "trace")] pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> { let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = self.defining_use_anchor?; + let parent_def_id = match self.defining_use_anchor { + DefiningAnchor::Bubble | DefiningAnchor::Error => return None, + DefiningAnchor::Bind(bind) => bind, + }; let item_kind = &self.tcx.hir().expect_item(def_id).kind; let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { @@ -433,7 +438,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } #[instrument(skip(self), level = "trace")] - fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { + pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { let origin = match self.tcx.hir().expect_item(def_id).kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin, ref itemkind => { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9c0b534798e..3eef3308770 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -718,6 +718,7 @@ fn test_unstable_options_tracking_hash() { tracked!(asm_comments, true); tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); + tracked!(box_noalias, Some(false)); tracked!( branch_protection, Some(BranchProtection { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c41a8318ec5..4491965347b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3266,7 +3266,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // this attribute doesn't make it UB for the pointed-to data to be undef. attrs.set(ArgAttribute::NoUndef); - // `Box` pointer parameters never alias because ownership is transferred + // The aliasing rules for `Box<T>` are still not decided, but currently we emit + // `noalias` for it. This can be turned off using an unstable flag. + // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326 + let noalias_for_box = + self.tcx().sess.opts.unstable_opts.box_noalias.unwrap_or(true); + // `&mut` pointer parameters never alias other parameters, // or mutable global data // @@ -3281,7 +3286,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // `-Zmutable-noalias` debugging option. let no_alias = match kind { PointerKind::Shared | PointerKind::UniqueBorrowed => false, - PointerKind::UniqueOwned => true, + PointerKind::UniqueOwned => noalias_for_box, PointerKind::Frozen => !is_return, }; if no_alias { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 01ff9e254f7..5d365fc5246 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1209,6 +1209,8 @@ options! { binary_dep_depinfo: bool = (false, parse_bool, [TRACKED], "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \ (default: no)"), + box_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED], + "emit noalias metadata for box (default: yes)"), branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED], "set options for branch target identification and pointer authentication on AArch64"), cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 6ca630b74cc..c2b2e319951 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -3,7 +3,7 @@ // seems likely that they should eventually be merged into more // general routines. -use crate::infer::TyCtxtInferExt; +use crate::infer::{DefiningAnchor, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, Unimplemented, @@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>( // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - tcx.infer_ctxt().enter(|infcx| { + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(|infcx| { + //~^ HACK `Bubble` is required for + // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs let mut selcx = SelectionContext::new(&infcx); let obligation_cause = ObligationCause::dummy(); @@ -69,7 +71,8 @@ pub fn codegen_fulfill_obligation<'tcx>( // Opaque types may have gotten their hidden types constrained, but we can ignore them safely // as they will get constrained elsewhere, too. - let _opaque_types = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); debug!("Cache miss: {trait_ref:?} => {impl_source:?}"); Ok(&*tcx.arena.alloc(impl_source)) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 69f3f03cfa9..9497d5c4528 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node, PathSegment}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; use rustc_middle::hir::nested_filter; @@ -731,52 +731,52 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| { - let ocx = ObligationCtxt::new(&infcx); - let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter( + move |infcx| { + let ocx = ObligationCtxt::new(&infcx); + let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); - let misc_cause = traits::ObligationCause::misc(span, hir_id); + let misc_cause = traits::ObligationCause::misc(span, hir_id); - match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) { - Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok), - Err(ty_err) => { - tcx.sess.delay_span_bug( - span, - &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"), - ); + match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) { + Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok), + Err(ty_err) => { + tcx.sess.delay_span_bug( + span, + &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"), + ); + } } - } - // Additionally require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = - ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx); - ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate)); - - // Check that all obligations are satisfied by the implementation's - // version. - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - infcx.report_fulfillment_errors(&errors, None, false); - } - - match origin { - // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} - // Can have different predicates to their defining use - hir::OpaqueTyOrigin::TyAlias => { - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( - defining_use_anchor, - &outlives_environment, - ); + // Additionally require the hidden type to be well-formed with only the generics of the opaque type. + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the + // hidden type is well formed even without those bounds. + let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())) + .to_predicate(tcx); + ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate)); + + // Check that all obligations are satisfied by the implementation's + // version. + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); } - } - - // Clean up after ourselves - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - }); + match origin { + // Checked when type checking the function containing them. + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} + // Can have different predicates to their defining use + hir::OpaqueTyOrigin::TyAlias => { + let outlives_environment = OutlivesEnvironment::new(param_env); + infcx.check_region_obligations_and_report_errors( + defining_use_anchor, + &outlives_environment, + ); + } + } + // Clean up after ourselves + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + }, + ); } fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 3fb8e5080f3..020aa95d0be 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1460,6 +1460,7 @@ pub fn check_type_bounds<'tcx>( .map(|e| e.map_bound(|e| *e).transpose_tuple2()) .map(|(bound, span)| { debug!(?bound); + // this is where opaque type is found let concrete_ty_bound = bound.subst(tcx, rebased_substs); debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); @@ -1481,7 +1482,6 @@ pub fn check_type_bounds<'tcx>( ocx.register_obligations(obligations); ocx.register_obligation(obligation); } - // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index e6fa95b91e9..e3db70845dd 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -573,6 +573,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If so, we might have just forgotten to wrap some args in a tuple. if let Some(ty::Tuple(tys)) = formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind()) + // If the tuple is unit, we're not actually wrapping any arguments. + && !tys.is_empty() && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() { // Wrap up the N provided arguments starting at this position in a tuple. diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index a2daf6886f1..9858cd8fa19 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -630,18 +630,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; let to_owned_msg = "create an owned `String` from a string reference"; - let string_type = self.tcx.get_diagnostic_item(sym::String); - let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() { - Some(ty_def) => Some(ty_def.did()) == string_type, - None => false, + let is_std_string = |ty: Ty<'tcx>| { + ty.ty_adt_def() + .map_or(false, |ty_def| self.tcx.is_diagnostic_item(sym::String, ty_def.did())) }; match (lhs_ty.kind(), rhs_ty.kind()) { (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str - if (*l_ty.kind() == Str || is_std_string(l_ty)) && ( - *r_ty.kind() == Str || is_std_string(r_ty) || - &format!("{:?}", rhs_ty) == "&&str" - ) => + if (*l_ty.kind() == Str || is_std_string(l_ty)) + && (*r_ty.kind() == Str + || is_std_string(r_ty) + || matches!( + r_ty.kind(), Ref(_, inner_ty, _) if *inner_ty.kind() == Str + )) => { if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); |
