-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Misc cleanups from reading some borrowck code #150141
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,12 @@ | ||
| //! Code to extract the universally quantified regions declared on a | ||
| //! function and the relationships between them. For example: | ||
| //! function. For example: | ||
| //! | ||
| //! ``` | ||
| //! fn foo<'a, 'b, 'c: 'b>() { } | ||
| //! ``` | ||
| //! | ||
| //! here we would return a map assigning each of `{'a, 'b, 'c}` | ||
| //! to an index, as well as the `FreeRegionMap` which can compute | ||
| //! relationships between them. | ||
| //! to an index. | ||
| //! | ||
| //! The code in this file doesn't *do anything* with those results; it | ||
| //! just returns them for other code to use. | ||
|
|
@@ -271,8 +270,7 @@ impl<'tcx> UniversalRegions<'tcx> { | |
| /// Creates a new and fully initialized `UniversalRegions` that | ||
| /// contains indices for all the free regions found in the given | ||
| /// MIR -- that is, all the regions that appear in the function's | ||
| /// signature. This will also compute the relationships that are | ||
| /// known between those regions. | ||
| /// signature. | ||
| pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self { | ||
| UniversalRegionsBuilder { infcx, mir_def }.build() | ||
| } | ||
|
|
@@ -648,10 +646,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { | |
|
|
||
| BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => { | ||
| let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); | ||
| if self.mir_def.to_def_id() == typeck_root_def_id | ||
| // Do not ICE when checking default_field_values consts with lifetimes (#135649) | ||
| && DefKind::Field != tcx.def_kind(tcx.parent(typeck_root_def_id)) | ||
| { | ||
| if self.mir_def.to_def_id() == typeck_root_def_id { | ||
| let args = self.infcx.replace_free_regions_with_nll_infer_vars( | ||
| NllRegionVariableOrigin::FreeRegion, | ||
| identity_args, | ||
|
|
@@ -699,30 +694,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { | |
| let tcx = self.infcx.tcx; | ||
| let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); | ||
| let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); | ||
| let fr_args = match defining_ty { | ||
| DefiningTy::Closure(_, args) | ||
| | DefiningTy::CoroutineClosure(_, args) | ||
| | DefiningTy::Coroutine(_, args) | ||
| | DefiningTy::InlineConst(_, args) => { | ||
| // In the case of closures, we rely on the fact that | ||
| // the first N elements in the ClosureArgs are | ||
| // inherited from the `typeck_root_def_id`. | ||
| // Therefore, when we zip together (below) with | ||
| // `identity_args`, we will get only those regions | ||
| // that correspond to early-bound regions declared on | ||
| // the `typeck_root_def_id`. | ||
| assert!(args.len() >= identity_args.len()); | ||
| assert_eq!(args.regions().count(), identity_args.regions().count()); | ||
| args | ||
| } | ||
|
|
||
| DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args, | ||
|
|
||
| DefiningTy::GlobalAsm(_) => ty::List::empty(), | ||
| }; | ||
| let renumbered_args = defining_ty.args(); | ||
|
|
||
| let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); | ||
| let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); | ||
| // This relies on typeck roots being generics_of parents with their | ||
| // parameters at the start of nested bodies' generics. | ||
| assert!(renumbered_args.len() >= identity_args.len()); | ||
|
Member
Author
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. I don't know how valuable this assert is in practice? I also would expect us to be relying on this invariant in more places in the compiler than just here 🤔 feels like more generally we expect all typeck parents to be generics_of parents and if that doesn't hold we probably want to yell somewhere other than here 🤔 |
||
| let arg_mapping = | ||
| iter::zip(identity_args.regions(), renumbered_args.regions().map(|r| r.as_var())); | ||
|
|
||
| UniversalRegionIndices { | ||
| indices: global_mapping.chain(arg_mapping).collect(), | ||
|
|
@@ -862,8 +841,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { | |
| }; | ||
|
|
||
| // FIXME(#129952): We probably want a more principled approach here. | ||
| if let Err(terr) = inputs_and_output.skip_binder().error_reported() { | ||
| self.infcx.set_tainted_by_errors(terr); | ||
| if let Err(e) = inputs_and_output.error_reported() { | ||
| self.infcx.set_tainted_by_errors(e); | ||
| } | ||
|
|
||
| inputs_and_output | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,92 +10,15 @@ use rustc_middle::ty::util::IntTypeExt; | |
| use rustc_middle::ty::{self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; | ||
| use rustc_middle::{bug, span_bug}; | ||
| use rustc_span::{DUMMY_SP, Ident, Span}; | ||
| use tracing::instrument; | ||
|
|
||
| use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder}; | ||
| use crate::check::wfcheck::check_static_item; | ||
| use crate::hir_ty_lowering::HirTyLowerer; | ||
|
|
||
| mod opaque; | ||
|
|
||
| fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { | ||
|
Member
Author
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. ive just moved this down because it's weird for |
||
| use hir::*; | ||
| use rustc_middle::ty::Ty; | ||
| let tcx = icx.tcx; | ||
| let hir_id = tcx.local_def_id_to_hir_id(def_id); | ||
|
|
||
| let node = tcx.hir_node(hir_id); | ||
| let Node::AnonConst(&AnonConst { span, .. }) = node else { | ||
| span_bug!( | ||
| tcx.def_span(def_id), | ||
| "expected anon const in `anon_const_type_of`, got {node:?}" | ||
| ); | ||
| }; | ||
|
|
||
| let parent_node_id = tcx.parent_hir_id(hir_id); | ||
| let parent_node = tcx.hir_node(parent_node_id); | ||
|
|
||
| match parent_node { | ||
| // Anon consts "inside" the type system. | ||
| Node::ConstArg(&ConstArg { | ||
| hir_id: arg_hir_id, | ||
| kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }), | ||
| .. | ||
| }) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span), | ||
|
|
||
| Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => { | ||
| tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) | ||
| } | ||
|
|
||
| Node::Field(&hir::FieldDef { default: Some(c), def_id: field_def_id, .. }) | ||
| if c.hir_id == hir_id => | ||
| { | ||
| tcx.type_of(field_def_id).instantiate_identity() | ||
| } | ||
|
|
||
| _ => Ty::new_error_with_message( | ||
| tcx, | ||
| span, | ||
| format!("unexpected anon const parent in type_of(): {parent_node:?}"), | ||
| ), | ||
| } | ||
| } | ||
|
|
||
| fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { | ||
| use hir::*; | ||
| use rustc_middle::ty::Ty; | ||
|
|
||
| let tcx = icx.tcx; | ||
|
|
||
| match tcx.parent_hir_node(arg_hir_id) { | ||
| // Array length const arguments do not have `type_of` fed as there is never a corresponding | ||
| // generic parameter definition. | ||
| Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) | ||
| | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) | ||
| if constant.hir_id == arg_hir_id => | ||
| { | ||
| tcx.types.usize | ||
| } | ||
|
|
||
| Node::TyPat(pat) => { | ||
| let node = match tcx.parent_hir_node(pat.hir_id) { | ||
| // Or patterns can be nested one level deep | ||
| Node::TyPat(p) => tcx.parent_hir_node(p.hir_id), | ||
| other => other, | ||
| }; | ||
| let hir::TyKind::Pat(ty, _) = node.expect_ty().kind else { bug!() }; | ||
| icx.lower_ty(ty) | ||
| } | ||
|
|
||
| // This is not a `bug!` as const arguments in path segments that did not resolve to anything | ||
| // will result in `type_of` never being fed. | ||
| _ => Ty::new_error_with_message( | ||
| tcx, | ||
| span, | ||
| "`type_of` called on const argument's anon const before the const argument was lowered", | ||
| ), | ||
| } | ||
| } | ||
|
|
||
| #[instrument(level = "debug", skip(tcx), ret)] | ||
| pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> { | ||
| use rustc_hir::*; | ||
| use rustc_middle::ty::Ty; | ||
|
|
@@ -408,6 +331,85 @@ pub(super) fn type_of_opaque_hir_typeck( | |
| } | ||
| } | ||
|
|
||
| fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { | ||
| use hir::*; | ||
| use rustc_middle::ty::Ty; | ||
| let tcx = icx.tcx; | ||
| let hir_id = tcx.local_def_id_to_hir_id(def_id); | ||
|
|
||
| let node = tcx.hir_node(hir_id); | ||
| let Node::AnonConst(&AnonConst { span, .. }) = node else { | ||
| span_bug!( | ||
| tcx.def_span(def_id), | ||
| "expected anon const in `anon_const_type_of`, got {node:?}" | ||
| ); | ||
| }; | ||
|
|
||
| let parent_node_id = tcx.parent_hir_id(hir_id); | ||
| let parent_node = tcx.hir_node(parent_node_id); | ||
|
|
||
| match parent_node { | ||
| // Anon consts "inside" the type system. | ||
| Node::ConstArg(&ConstArg { | ||
| hir_id: arg_hir_id, | ||
| kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }), | ||
| .. | ||
| }) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span), | ||
|
|
||
| Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => { | ||
| tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) | ||
| } | ||
|
|
||
| Node::Field(&hir::FieldDef { default: Some(c), def_id: field_def_id, .. }) | ||
| if c.hir_id == hir_id => | ||
| { | ||
| tcx.type_of(field_def_id).instantiate_identity() | ||
| } | ||
|
|
||
| _ => Ty::new_error_with_message( | ||
| tcx, | ||
| span, | ||
| format!("unexpected anon const parent in type_of(): {parent_node:?}"), | ||
| ), | ||
| } | ||
| } | ||
|
|
||
| fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { | ||
| use hir::*; | ||
| use rustc_middle::ty::Ty; | ||
|
|
||
| let tcx = icx.tcx; | ||
|
|
||
| match tcx.parent_hir_node(arg_hir_id) { | ||
| // Array length const arguments do not have `type_of` fed as there is never a corresponding | ||
| // generic parameter definition. | ||
| Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) | ||
| | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) | ||
| if constant.hir_id == arg_hir_id => | ||
| { | ||
| tcx.types.usize | ||
| } | ||
|
|
||
| Node::TyPat(pat) => { | ||
| let node = match tcx.parent_hir_node(pat.hir_id) { | ||
| // Or patterns can be nested one level deep | ||
| Node::TyPat(p) => tcx.parent_hir_node(p.hir_id), | ||
| other => other, | ||
| }; | ||
| let hir::TyKind::Pat(ty, _) = node.expect_ty().kind else { bug!() }; | ||
| icx.lower_ty(ty) | ||
| } | ||
|
|
||
| // This is not a `bug!` as const arguments in path segments that did not resolve to anything | ||
| // will result in `type_of` never being fed. | ||
| _ => Ty::new_error_with_message( | ||
| tcx, | ||
| span, | ||
| "`type_of` called on const argument's anon const before the const argument was lowered", | ||
| ), | ||
| } | ||
| } | ||
|
|
||
| fn infer_placeholder_type<'tcx>( | ||
| cx: &dyn HirTyLowerer<'tcx>, | ||
| def_id: LocalDefId, | ||
|
|
||
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.
This was erroneously added in #135711 to work around the fact that
generics_offor default field values was wrong (Noneparent) resulting inidentity_argsbeing empty. It was then fixed properly in #137913 with neither errs or myself realising this logic existed so this can just be removed now