diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-04-17 10:19:41 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-05-12 10:24:03 +0000 |
| commit | f08b51759763e44fc59b56584b640c2d2ccff0a0 (patch) | |
| tree | a92628d0ba91c465c0ba55e98da3d76f073d94f7 | |
| parent | 699a862a3d4e4a2d5603c93297c0c44021ea72f5 (diff) | |
| download | rust-f08b51759763e44fc59b56584b640c2d2ccff0a0.tar.gz rust-f08b51759763e44fc59b56584b640c2d2ccff0a0.zip | |
Require `impl Trait` in associated types to appear in method signatures
20 files changed, 242 insertions, 53 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3d154a93fb2..08ee3761bac 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -305,7 +305,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ); this.arena.alloc(this.ty(span, hir::TyKind::Err(guar))) } - Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), + Some(ty) => this.lower_ty( + ty, + &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, + ), }, ); hir::ItemKind::TyAlias(ty, generics) @@ -852,7 +855,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ImplItemKind::Type(ty) } Some(ty) => { - let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty( + ty, + &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, + ); hir::ImplItemKind::Type(ty) } }, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1fd7cc66470..cd6614a54a4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -247,7 +247,7 @@ enum ImplTraitContext { in_trait: bool, }, /// Impl trait in type aliases. - TypeAliasesOpaqueTy, + TypeAliasesOpaqueTy { in_assoc_ty: bool }, /// `impl Trait` is unstably accepted in this position. FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. @@ -1407,14 +1407,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { *in_trait, itctx, ), - ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( - span, - hir::OpaqueTyOrigin::TyAlias, - *def_node_id, - bounds, - false, - itctx, - ), + &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self + .lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty }, + *def_node_id, + bounds, + false, + itctx, + ), ImplTraitContext::Universal => { let span = t.span; self.create_def( @@ -1534,13 +1535,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want // to capture the lifetimes that appear in the bounds. So visit the bounds to find out // exactly which ones those are. - let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias { - // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters - Vec::new() - } else { - // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, - // we only keep the lifetimes that appear in the `impl Debug` itself: - lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + let lifetimes_to_remap = match origin { + hir::OpaqueTyOrigin::TyAlias { .. } => { + // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters + Vec::new() + } + hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..) => { + // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, + // we only keep the lifetimes that appear in the `impl Debug` itself: + lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + } }; debug!(?lifetimes_to_remap); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4970ece5e7d..309f23d9226 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -265,7 +265,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs` // on stable and we'd break that. - let OpaqueTyOrigin::TyAlias = origin else { + let OpaqueTyOrigin::TyAlias { .. } = origin else { return definition_ty; }; let def_id = opaque_type_key.def_id; @@ -360,7 +360,7 @@ fn check_opaque_type_parameter_valid( // which would error here on all of the `'static` args. OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()), // Check these - OpaqueTyOrigin::TyAlias => {} + OpaqueTyOrigin::TyAlias { .. } => {} } let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 38cd5865cc3..932f0396282 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2662,7 +2662,10 @@ pub enum OpaqueTyOrigin { /// `async fn` AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` - TyAlias, + TyAlias { + /// associated types in impl blocks for traits. + in_assoc_ty: bool, + }, } /// The various kinds of types recognized by the compiler. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 5187e63f8e3..b16860907eb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -397,7 +397,14 @@ fn check_opaque_meets_bounds<'tcx>( ) { let defining_use_anchor = match *origin { hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, - hir::OpaqueTyOrigin::TyAlias => def_id, + hir::OpaqueTyOrigin::TyAlias { .. } => { + let mut def_id = def_id; + // Find the surrounding item (type alias or assoc type) + while let DefKind::OpaqueTy = tcx.def_kind(def_id) { + def_id = tcx.local_parent(def_id); + } + def_id + } }; let param_env = tcx.param_env(defining_use_anchor); @@ -455,10 +462,10 @@ fn check_opaque_meets_bounds<'tcx>( // They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`. // We don't have to check them here because their well-formedness follows from the WF of // the projection input types in the defining- and use-sites. - hir::OpaqueTyOrigin::TyAlias + hir::OpaqueTyOrigin::TyAlias { .. } if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {} // Can have different predicates to their defining use - hir::OpaqueTyOrigin::TyAlias => { + hir::OpaqueTyOrigin::TyAlias { .. } => { let wf_tys = ocx.assumed_wf_types(param_env, span, def_id); let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b65817ee95e..2f808d4ce73 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1483,7 +1483,7 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorK fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { match tcx.hir().get_by_def_id(def_id) { Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => { - matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) + matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }) } _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id), } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ab2932bf969..ed60998ec8d 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -159,7 +159,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } Some(fn_def_id.to_def_id()) } - ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { .. }, + .. + }) => { let parent_id = tcx.hir().get_parent_item(hir_id); assert_ne!(parent_id, hir::CRATE_OWNER_ID); debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index e04658c8e77..a33990813b8 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -721,7 +721,7 @@ pub(super) fn type_param_predicates( | ItemKind::TyAlias(_, generics) | ItemKind::OpaqueTy(OpaqueTy { generics, - origin: hir::OpaqueTyOrigin::TyAlias, + origin: hir::OpaqueTyOrigin::TyAlias { .. }, .. }) | ItemKind::Enum(_, generics) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 5c7f7f10b17..92ae93cf4cc 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -526,7 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }); } hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias, .. + origin: hir::OpaqueTyOrigin::TyAlias { .. }, + .. }) => { // Opaque types are visited when we visit the // `TyKind::OpaqueDef`, so that they have the lifetimes from @@ -707,7 +708,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let opaque_ty = self.tcx.hir().item(item_id); match &opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias, + origin: hir::OpaqueTyOrigin::TyAlias { .. }, .. }) => { intravisit::walk_ty(self, ty); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8df0166f76b..6c7c2b9eea2 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -426,9 +426,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { - find_opaque_ty_constraints_for_tait(tcx, def_id) - } + ItemKind::OpaqueTy(OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { .. }, + .. + }) => find_opaque_ty_constraints_for_tait(tcx, def_id), // Opaque types desugared from `impl Trait`. ItemKind::OpaqueTy(OpaqueTy { origin: diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9e78e6acba5..b7253957edc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -735,7 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id).is_some() { + && self.opaque_type_origin(def_id, self.param_env).is_some() { return None; } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 064811bd29d..e9c3726f8c3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -1,8 +1,10 @@ +use crate::infer::opaque_types::may_define_impl_trait_in_assoc_ty_modulo_sig; + use super::TypeErrCtxt; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; -use rustc_middle::traits::ObligationCauseCode; +use rustc_middle::traits::ObligationCauseCode::{self, MiscObligation}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::Printer; use rustc_middle::{ @@ -256,6 +258,15 @@ impl<T> Trait<T> for X { ); } } + (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if matches!(cause.code(), MiscObligation) => { + if let Some(def_id) = alias.def_id.as_local() { + if may_define_impl_trait_in_assoc_ty_modulo_sig(tcx, body_owner_def_id.expect_local(), def_id).is_some() { + diag.span_note(tcx.def_span(body_owner_def_id), "\ + this item must have the opaque type in its signature \ + in order to be able to register hidden types"); + } + } + } (ty::FnPtr(_), ty::FnDef(def, _)) if let hir::def::DefKind::Fn = tcx.def_kind(def) => { diag.note( diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 362b22b23a8..0b6f51652fd 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -3,9 +3,10 @@ use super::{DefineOpaqueTypes, InferResult}; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; +use hir::def::DefKind; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_middle::traits::ObligationCause; @@ -53,7 +54,9 @@ impl<'tcx> InferCtxt<'tcx> { } let mut obligations = vec![]; let replace_opaque_type = |def_id: DefId| { - def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some()) + def_id + .as_local() + .map_or(false, |def_id| self.opaque_type_origin(def_id, param_env).is_some()) }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, @@ -138,7 +141,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id)? + self.opaque_type_origin(def_id, param_env)? } DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id), DefiningAnchor::Error => return None, @@ -149,8 +152,9 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias) = - b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) + if let Some(OpaqueTyOrigin::TyAlias { .. }) = b_def_id + .as_local() + .and_then(|b_def_id| self.opaque_type_origin(b_def_id, param_env)) { self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -366,8 +370,12 @@ impl<'tcx> InferCtxt<'tcx> { /// Returns the origin of the opaque type `def_id` if we're currently /// in its defining scope. - #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> { + #[instrument(skip(self, param_env), level = "trace", ret)] + pub fn opaque_type_origin( + &self, + def_id: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + ) -> Option<OpaqueTyOrigin> { let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, @@ -381,8 +389,12 @@ impl<'tcx> InferCtxt<'tcx> { // Anonymous `impl Trait` hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::OpaqueTyOrigin::TyAlias => { - may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { + if in_assoc_ty { + may_define_impl_trait_in_assoc_ty(self.tcx, parent_def_id, def_id, param_env) + } else { + may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) + } } }; in_definition_scope.then_some(origin) @@ -642,3 +654,105 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi ); res } + +#[derive(Debug, TypeVisitable, Clone)] +/// Helper datastructure containing the signature +/// that the opaque type extraction logic uses for determining +/// whether an opaque type may have its hidden types registered +/// by an item. +enum FnSigOrTy<'tcx> { + FnSig(ty::PolyFnSig<'tcx>), + Ty(Ty<'tcx>), +} + +/// Checks that the item may register hidden types for the +/// opaque type, if the opaque type shows up in its signature. +#[instrument(level = "debug", skip(tcx), ret)] +pub fn may_define_impl_trait_in_assoc_ty_modulo_sig<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + opaque_def_id: LocalDefId, +) -> Option<impl TypeVisitable<TyCtxt<'tcx>>> { + let sig = match tcx.def_kind(def_id) { + DefKind::AssocFn => FnSigOrTy::FnSig(tcx.fn_sig(def_id).subst_identity()), + DefKind::AssocConst | DefKind::AssocTy => { + FnSigOrTy::Ty(tcx.type_of(def_id).subst_identity()) + } + _ => return None, + }; + let impl_id = tcx.local_parent(def_id); + trace!(?impl_id); + let mut assoc_id = opaque_def_id; + // Peel nested opaque types. + while let DefKind::OpaqueTy = tcx.def_kind(assoc_id) { + trace!(?assoc_id); + assoc_id = tcx.local_parent(assoc_id); + } + trace!(?assoc_id); + if !matches!(tcx.def_kind(assoc_id), DefKind::AssocTy) { + tcx.sess + .delay_span_bug(tcx.def_span(opaque_def_id), format!("{:?}", tcx.def_kind(assoc_id))); + } + let assoc_impl_id = tcx.local_parent(assoc_id); + trace!(?assoc_impl_id); + + if impl_id != assoc_impl_id { + return None; + } + + Some(sig) +} + +#[instrument(level = "debug", skip(tcx, param_env), ret)] +fn may_define_impl_trait_in_assoc_ty<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + opaque_def_id: LocalDefId, + param_env: ty::ParamEnv<'tcx>, +) -> bool { + let Some(sig) = may_define_impl_trait_in_assoc_ty_modulo_sig(tcx, def_id, opaque_def_id) else { + return false; + }; + + struct Visitor<'tcx> { + opaque_def_id: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + tcx: TyCtxt<'tcx>, + seen: FxHashSet<LocalDefId>, + } + + impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> { + type BreakTy = (); + #[instrument(level = "trace", skip(self), ret)] + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + // FIXME(oli-obk): We should be checking if the associated type + // is mentioned instead of normalizing to find the opaque type. + // But that requires a way to figure out that a projection refers + // to a specific opaque type. That is probably doable by checking for + // `Self` as the `substs[0]`. + let normalized_ty = self.tcx.normalize_erasing_regions(self.param_env, ty); + if let ty::Alias(ty::Opaque, alias) = normalized_ty.kind() { + if let Some(def_id) = alias.def_id.as_local() { + trace!(?alias.def_id); + if def_id == self.opaque_def_id { + return ControlFlow::Break(()); + } + + if self.seen.insert(def_id) { + // Look into nested obligations like `impl Trait<Assoc = impl OtherTrait>`. + for (pred, _) in self + .tcx + .explicit_item_bounds(alias.def_id) + .subst_iter_copied(self.tcx, alias.substs) + { + pred.visit_with(self)?; + } + } + } + } + normalized_ty.super_visit_with(self) + } + } + sig.visit_with(&mut Visitor { opaque_def_id, param_env, tcx, seen: Default::default() }) + .is_break() +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 29cf432b8f9..043410c47e0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1641,9 +1641,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(ref opaque) => { self.encode_explicit_item_bounds(def_id); - self.tables - .is_type_alias_impl_trait - .set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)); + self.tables.is_type_alias_impl_trait.set( + def_id.index, + matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }), + ); } hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set_some(def_id.index, *defaultness); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f882f54d628..2952217f267 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2520,7 +2520,7 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { Some(parent) } - hir::OpaqueTyOrigin::TyAlias => None, + hir::OpaqueTyOrigin::TyAlias { .. } => None, }; } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 9332b0430ff..a0c8d299f48 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -32,7 +32,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. - #[tracing::instrument(level = "debug", skip(self, param_env))] + #[tracing::instrument(level = "debug", skip(self, param_env), ret)] pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T where T: TypeFoldable<TyCtxt<'tcx>>, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index deb29b1e7a9..ff13daa6db4 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -455,7 +455,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias, .. + origin: hir::OpaqueTyOrigin::TyAlias { .. }, + .. }) | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) diff --git a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs index 551815d021a..21c1d8bcc98 100644 --- a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs @@ -5,15 +5,14 @@ trait Trait { type Opaque1; type Opaque2; - fn constrain(self); + fn constrain(self) -> (Self::Opaque1, Self::Opaque2); } impl<'a> Trait for &'a () { type Opaque1 = impl Sized; type Opaque2 = impl Sized + 'a; - fn constrain(self) { - let _: Self::Opaque1 = (); - let _: Self::Opaque2 = self; + fn constrain(self) -> (Self::Opaque1, Self::Opaque2) { + ((), self) } } diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs new file mode 100644 index 00000000000..93c52126d69 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs @@ -0,0 +1,16 @@ +#![feature(impl_trait_in_assoc_type)] + +trait Foo { + type Foo; + fn bar(); +} + +impl Foo for () { + type Foo = impl std::fmt::Debug; + fn bar() { + let x: Self::Foo = (); + //~^ ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr new file mode 100644 index 00000000000..2beed73cb85 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/invalid_impl_trait_in_assoc_ty.rs:11:28 + | +LL | type Foo = impl std::fmt::Debug; + | -------------------- the expected opaque type +LL | fn bar() { +LL | let x: Self::Foo = (); + | --------- ^^ expected opaque type, found `()` + | | + | expected due to this + | + = note: expected opaque type `<() as Foo>::Foo` + found unit type `()` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5 + | +LL | fn bar() { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. |
