-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Remove 'static requirement on try_as_dyn #150161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,15 @@ | ||
| use std::ops::ControlFlow; | ||
|
|
||
| use rustc_ast as ast; | ||
| use rustc_data_structures::fx::FxHashMap; | ||
| use rustc_hir::def_id::DefId; | ||
| use rustc_macros::{HashStable, TyDecodable, TyEncodable}; | ||
| use rustc_span::{Span, Symbol, kw}; | ||
| use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor}; | ||
| use tracing::instrument; | ||
|
|
||
| use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized}; | ||
| use crate::ty; | ||
| use crate::ty::{EarlyBinder, GenericArgsRef}; | ||
| use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind}; | ||
|
|
||
| #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] | ||
| pub enum GenericParamDefKind { | ||
|
|
@@ -436,6 +438,70 @@ impl<'tcx> GenericPredicates<'tcx> { | |
| instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| Unnormalized::new(*p))); | ||
| instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); | ||
| } | ||
|
|
||
| /// Allow simple where bounds like `T: Debug`, but prevent any kind of | ||
| /// outlives bounds or uses of generic parameters on the right hand side. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this feels kind of arbitrary to me, |
||
| pub fn is_fully_generic_for_reflection(self) -> bool { | ||
| struct ParamChecker; | ||
| impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamChecker { | ||
| type Result = ControlFlow<()>; | ||
| fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { | ||
| match r.kind() { | ||
| RegionKind::ReEarlyParam(_) | RegionKind::ReStatic | RegionKind::ReError(_) => { | ||
| ControlFlow::Break(()) | ||
| } | ||
| RegionKind::ReVar(_) | ||
| | RegionKind::RePlaceholder(_) | ||
| | RegionKind::ReErased | ||
| | RegionKind::ReLateParam(_) => { | ||
| bug!("unexpected lifetime in impl: {r:?}") | ||
| } | ||
| RegionKind::ReBound(..) => ControlFlow::Continue(()), | ||
| } | ||
| } | ||
|
|
||
| fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no |
||
| match t.kind() { | ||
| TyKind::Param(_p) => { | ||
| // Reject using parameters used in the type in where bounds | ||
| return ControlFlow::Break(()); | ||
| } | ||
| TyKind::Alias(..) => return ControlFlow::Break(()), | ||
| _ => (), | ||
| } | ||
| t.super_visit_with(self) | ||
| } | ||
| } | ||
|
|
||
| // Pessimistic: if any of the parameters have where bounds | ||
| // don't allow this impl to be used. | ||
| self.predicates.iter().all(|(clause, _)| { | ||
| match clause.kind().skip_binder() { | ||
| ClauseKind::Trait(trait_predicate) => { | ||
| // In a `T: Trait`, if the rhs bound does not contain any generic params | ||
| // or 'static lifetimes, then it cannot transitively cause such requirements, | ||
| // considering we apply the fully-generic-for-reflection rules to any impls for | ||
| // that trait, too. | ||
| if matches!(trait_predicate.self_ty().kind(), ty::Param(_)) | ||
| && trait_predicate.trait_ref.args[1..] | ||
| .iter() | ||
| .all(|arg| arg.visit_with(&mut ParamChecker).is_continue()) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
| ClauseKind::RegionOutlives(_) | ||
| | ClauseKind::TypeOutlives(_) | ||
| | ClauseKind::Projection(_) | ||
| | ClauseKind::ConstArgHasType(_, _) | ||
| | ClauseKind::WellFormed(_) | ||
| | ClauseKind::ConstEvaluatable(_) | ||
| | ClauseKind::HostEffect(_) | ||
| | ClauseKind::UnstableFeature(_) => {} | ||
| } | ||
| clause.visit_with(&mut ParamChecker).is_continue() | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| /// `[const]` bounds for a given item. This is represented using a struct much like | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ use std::fmt::Debug; | |
| use std::hash::{Hash, Hasher}; | ||
| use std::marker::PhantomData; | ||
| use std::num::NonZero; | ||
| use std::ops::ControlFlow; | ||
| use std::ptr::NonNull; | ||
| use std::{assert_matches, fmt, iter, str}; | ||
|
|
||
|
|
@@ -258,6 +259,59 @@ pub struct ImplTraitHeader<'tcx> { | |
| pub constness: hir::Constness, | ||
| } | ||
|
|
||
| impl<'tcx> ImplTraitHeader<'tcx> { | ||
| /// For trait impls, checks whether the type and trait only have generic lifetime parameters in their | ||
| /// arguments and only use any generic param once. | ||
| /// This is a pessimistic analysis, so it will reject alias types | ||
| /// and other types that may be actually ok. We can allow more in the future. | ||
| pub fn is_fully_generic_for_reflection(self) -> bool { | ||
| #[derive(Default)] | ||
| struct ParamFinder { | ||
| seen: FxHashSet<u32>, | ||
| } | ||
|
|
||
| impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamFinder { | ||
| type Result = ControlFlow<()>; | ||
| fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { | ||
| match r.kind() { | ||
| RegionKind::ReEarlyParam(param) => { | ||
| if self.seen.insert(param.index) { | ||
| ControlFlow::Continue(()) | ||
| } else { | ||
| ControlFlow::Break(()) | ||
| } | ||
| } | ||
| RegionKind::ReBound(..) => ControlFlow::Continue(()), | ||
| RegionKind::ReStatic | RegionKind::ReError(_) => ControlFlow::Break(()), | ||
| RegionKind::ReVar(_) | ||
| | RegionKind::RePlaceholder(_) | ||
| | RegionKind::ReErased | ||
| | RegionKind::ReLateParam(_) => bug!("unexpected lifetime in impl: {r:?}"), | ||
| } | ||
| } | ||
|
|
||
| fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no |
||
| match t.kind() { | ||
| TyKind::Param(p) => { | ||
| // Reject using a parameter twice (e.g. in `Foo<T, T>`) | ||
| if !self.seen.insert(p.index) { | ||
| return ControlFlow::Break(()); | ||
| } | ||
| } | ||
| TyKind::Alias(..) => return ControlFlow::Break(()), | ||
| _ => (), | ||
| } | ||
| t.super_visit_with(self) | ||
| } | ||
| } | ||
| self.trait_ref | ||
| .instantiate_identity() | ||
| .skip_norm_wip() | ||
| .visit_with(&mut ParamFinder::default()) | ||
| .is_continue() | ||
| } | ||
| } | ||
|
|
||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] | ||
| #[derive(TypeFoldable, TypeVisitable, Default)] | ||
| pub enum Asyncness { | ||
|
|
@@ -1036,6 +1090,7 @@ impl<'tcx> TypingEnv<'tcx> { | |
| let TypingEnv { typing_mode, param_env } = self; | ||
| match typing_mode.0 { | ||
| TypingMode::Coherence | ||
| | TypingMode::Reflection | ||
| | TypingMode::Analysis { .. } | ||
| | TypingMode::Borrowck { .. } | ||
| | TypingMode::PostBorrowckAnalysis { .. } => {} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't need to check elaborated clauses does that mean we actually don't need to check any predicates since we'll wind up proving them in
Reflectionmode tooView changes since the review