From 64c5b9a3d6f26659e0bd388fbb00cd92d888178d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 15:49:43 +0000 Subject: [PATCH] Add backcompat hack to support ```rust fn foo() -> impl MyTrait { panic!(); MyStruct } struct MyStruct; trait MyTrait {} impl MyTrait for MyStruct {} ``` --- compiler/rustc_middle/src/ty/context.rs | 11 +++++++--- compiler/rustc_typeck/src/check/writeback.rs | 10 +++++++-- compiler/rustc_typeck/src/collect/type_of.rs | 23 ++++++++++---------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5dae4b9e4c9..694b7d2b817 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -30,6 +30,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -464,9 +465,13 @@ pub struct TypeckResults<'tcx> { /// this field will be set to `Some(ErrorReported)`. pub tainted_by_errors: Option, - /// All the opaque types that are restricted to concrete types - /// by this function. - pub concrete_opaque_types: FxHashSet, + /// All the opaque types that have hidden types set + /// by this function. For return-position-impl-trait we also store the + /// type here, so that mir-borrowck can figure out hidden types, + /// even if they are only set in dead code (which doesn't show up in MIR). + /// For type-alias-impl-trait, this map is only used to prevent query cycles, + /// so the hidden types are all `None`. + pub concrete_opaque_types: VecMap>>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f97fedd9a6d..e04c1423cda 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -499,8 +499,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self) { let opaque_types = self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - for (opaque_type_key, _) in opaque_types { - self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id); + for (opaque_type_key, decl) in opaque_types { + let hidden_type = match decl.origin { + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { + Some(self.resolve(decl.hidden_type.ty, &decl.hidden_type.span)) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; + self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index ce2f486bb70..81faacd4da5 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -389,21 +389,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() .unwrap_or_else(|| { - if let Some(ErrorReported) = - tcx.typeck(owner).tainted_by_errors - { + let table = tcx.typeck(owner); + if let Some(ErrorReported) = table.tainted_by_errors { // Some error in the // owner fn prevented us from populating // the `concrete_opaque_types` table. tcx.ty_error() } else { - // We failed to resolve the opaque type or it - // resolves to itself. We interpret this as the - // no values of the hidden type ever being constructed, - // so we can just make the hidden type be `!`. - // For backwards compatibility reasons, we fall back to - // `()` until we the diverging default is changed. - tcx.mk_diverging_default() + table.concrete_opaque_types.get(&def_id.to_def_id()).copied().unwrap_or_else(|| { + // We failed to resolve the opaque type or it + // resolves to itself. We interpret this as the + // no values of the hidden type ever being constructed, + // so we can just make the hidden type be `!`. + // For backwards compatibility reasons, we fall back to + // `()` until we the diverging default is changed. + Some(tcx.mk_diverging_default()) + }).expect("RPIT always have a hidden type from typeck") } }); debug!("concrete_ty = {:?}", concrete_ty); @@ -597,7 +598,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. - if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) { + if self.tcx.typeck(def_id).concrete_opaque_types.get(&self.def_id).is_none() { debug!("no constraints in typeck results"); return; }