Skip to content

Commit dfa5c33

Browse files
committed
Remove 'static requirement on try_as_dyn
1 parent e8f3cfc commit dfa5c33

32 files changed

Lines changed: 308 additions & 20 deletions

File tree

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
236236
};
237237

238238
let (infcx, param_env) =
239-
self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
239+
self.tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv {
240+
typing_mode: ty::TypingMode::Reflection,
241+
..self.typing_env
242+
});
240243

241244
let ocx = ObligationCtxt::new(&infcx);
242245
ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| {

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub(crate) fn provide(providers: &mut Providers) {
8989
adt_def,
9090
fn_sig,
9191
impl_trait_header,
92+
impl_is_fully_generic_for_reflection,
9293
coroutine_kind,
9394
coroutine_for_closure,
9495
opaque_ty_origin,
@@ -1266,6 +1267,12 @@ pub fn suggest_impl_trait<'tcx>(
12661267
None
12671268
}
12681269

1270+
fn impl_is_fully_generic_for_reflection(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
1271+
tcx.type_of(def_id).instantiate_identity().is_fully_generic_for_reflection().is_ok_and(
1272+
|params| tcx.explicit_predicates_of(def_id).is_fully_generic_for_reflection(params),
1273+
)
1274+
}
1275+
12691276
fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
12701277
let icx = ItemCtxt::new(tcx, def_id);
12711278
let item = tcx.hir_expect_item(def_id);

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,7 @@ impl<'tcx> InferCtxt<'tcx> {
10471047
// and post-borrowck analysis mode. We may need to modify its uses
10481048
// to support PostBorrowckAnalysis in the old solver as well.
10491049
TypingMode::Coherence
1050+
| TypingMode::Reflection
10501051
| TypingMode::PostBorrowckAnalysis { .. }
10511052
| TypingMode::PostAnalysis => false,
10521053
}
@@ -1371,6 +1372,7 @@ impl<'tcx> InferCtxt<'tcx> {
13711372
}
13721373
mode @ (ty::TypingMode::Coherence
13731374
| ty::TypingMode::PostBorrowckAnalysis { .. }
1375+
| ty::TypingMode::Reflection
13741376
| ty::TypingMode::PostAnalysis) => mode,
13751377
};
13761378
ty::TypingEnv { typing_mode, param_env }

compiler/rustc_infer/src/infer/opaque_types/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ impl<'tcx> InferCtxt<'tcx> {
276276
.map(|obligation| obligation.as_goal()),
277277
);
278278
}
279-
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
279+
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. }
280+
| ty::TypingMode::PostAnalysis
281+
| ty::TypingMode::Reflection) => {
280282
bug!("insert hidden type in {mode:?}")
281283
}
282284
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ provide! { tcx, def_id, other, cdata,
236236
fn_sig => { table }
237237
codegen_fn_attrs => { table }
238238
impl_trait_header => { table }
239+
impl_is_fully_generic_for_reflection => { table_direct }
239240
const_param_default => { table }
240241
object_lifetime_default => { table }
241242
thir_abstract_const => { table }

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
21672167
let header = tcx.impl_trait_header(def_id);
21682168
record!(self.tables.impl_trait_header[def_id] <- header);
21692169

2170+
let impl_is_fully_generic_for_reflection =
2171+
tcx.impl_is_fully_generic_for_reflection(def_id);
2172+
self.tables
2173+
.impl_is_fully_generic_for_reflection
2174+
.set(def_id.index, impl_is_fully_generic_for_reflection);
2175+
21702176
self.tables.defaultness.set(def_id.index, tcx.defaultness(def_id));
21712177

21722178
let trait_ref = header.trait_ref.instantiate_identity();

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ define_tables! {
407407
constness: Table<DefIndex, hir::Constness>,
408408
safety: Table<DefIndex, hir::Safety>,
409409
defaultness: Table<DefIndex, hir::Defaultness>,
410+
impl_is_fully_generic_for_reflection: Table<DefIndex, bool>,
410411

411412
- optional:
412413
attributes: Table<DefIndex, LazyArray<hir::Attribute>>,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,15 @@ rustc_queries! {
11271127
separate_provide_extern
11281128
}
11291129

1130+
/// Whether all generic parameters of the type are unique unconstrained generic parameters
1131+
/// of the impl. `Bar<'static>` or `Foo<'a, 'a>` or outlives bounds on the lifetimes cause
1132+
/// this boolean to be false and `try_as_dyn` to return `None`.
1133+
query impl_is_fully_generic_for_reflection(impl_id: DefId) -> bool {
1134+
desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
1135+
cache_on_disk_if { impl_id.is_local() }
1136+
separate_provide_extern
1137+
}
1138+
11301139
/// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due
11311140
/// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct
11321141
/// whose tail is one of those types.

compiler/rustc_middle/src/ty/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
690690
self.impl_polarity(impl_def_id)
691691
}
692692

693+
fn is_fully_generic_for_reflection(self, impl_def_id: Self::ImplId) -> bool {
694+
self.impl_is_fully_generic_for_reflection(impl_def_id)
695+
}
696+
693697
fn trait_is_auto(self, trait_def_id: DefId) -> bool {
694698
self.trait_is_auto(trait_def_id)
695699
}

compiler/rustc_middle/src/ty/generics.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
use std::ops::ControlFlow;
2+
13
use rustc_ast as ast;
2-
use rustc_data_structures::fx::FxHashMap;
4+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
35
use rustc_hir::def_id::DefId;
46
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
57
use rustc_span::{Span, Symbol, kw};
8+
use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor};
69
use tracing::instrument;
710

811
use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
9-
use crate::ty;
10-
use crate::ty::{EarlyBinder, GenericArgsRef};
12+
use crate::ty::{self, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind};
1113

1214
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
1315
pub enum GenericParamDefKind {
@@ -417,6 +419,54 @@ impl<'tcx> GenericPredicates<'tcx> {
417419
instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p));
418420
instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
419421
}
422+
423+
pub fn is_fully_generic_for_reflection(self, params: FxHashSet<u32>) -> bool {
424+
#[derive(Default)]
425+
struct ParamChecker {
426+
params: FxHashSet<u32>,
427+
}
428+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamChecker {
429+
type Result = ControlFlow<()>;
430+
fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result {
431+
match r.kind() {
432+
RegionKind::ReEarlyParam(param) => {
433+
if self.params.contains(&param.index) {
434+
ControlFlow::Break(())
435+
} else {
436+
ControlFlow::Continue(())
437+
}
438+
}
439+
RegionKind::ReBound(..)
440+
| RegionKind::ReLateParam(_)
441+
| RegionKind::ReStatic
442+
| RegionKind::ReVar(_)
443+
| RegionKind::RePlaceholder(_)
444+
| RegionKind::ReErased
445+
| RegionKind::ReError(_) => ControlFlow::Continue(()),
446+
}
447+
}
448+
449+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
450+
match t.kind() {
451+
TyKind::Param(p) => {
452+
// Reject using parameters used in the type in where bounds
453+
if self.params.contains(&p.index) {
454+
return ControlFlow::Break(());
455+
}
456+
}
457+
TyKind::Alias(..) => return ControlFlow::Break(()),
458+
_ => (),
459+
}
460+
t.super_visit_with(self)
461+
}
462+
}
463+
464+
let mut checker = ParamChecker { params };
465+
466+
// Pessimistic: if any of the lifetimes used in the type show up in where bounds
467+
// don't allow this impl to be used.
468+
self.predicates.iter().all(|(clause, _)| clause.visit_with(&mut checker).is_continue())
469+
}
420470
}
421471

422472
/// `[const]` bounds for a given item. This is represented using a struct much like

0 commit comments

Comments
 (0)