From 9bdba7b04e5c75b6e42c15ef8b78ec00dae7a65a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 30 Aug 2024 17:01:28 -0400 Subject: [PATCH 1/8] Parsing unsafe binders --- compiler/rustc_ast/src/ast.rs | 8 ++++++++ compiler/rustc_ast/src/mut_visit.rs | 5 +++++ compiler/rustc_ast/src/util/classify.rs | 4 ++++ compiler/rustc_ast/src/visit.rs | 4 ++++ compiler/rustc_ast_pretty/src/pprust/state.rs | 8 ++++++++ compiler/rustc_parse/src/parser/ty.rs | 12 ++++++++++++ 6 files changed, 41 insertions(+) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 37f429cce44d7..f4a0908c31473 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2148,6 +2148,12 @@ pub struct BareFnTy { pub decl_span: Span, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct UnsafeBinderTy { + pub generic_params: ThinVec, + pub inner_ty: P, +} + /// The various kinds of type recognized by the compiler. // // Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`. @@ -2163,6 +2169,8 @@ pub enum TyKind { Ref(Option, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P), + /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`). + UnsafeBinder(P), /// The never type (`!`). Never, /// A tuple (`(A, B, C, D,...)`). diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 104f84f26e0af..4559bf049592e 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -496,6 +496,11 @@ pub fn walk_ty(vis: &mut T, ty: &mut P) { vis.visit_fn_decl(decl); vis.visit_span(decl_span); } + TyKind::UnsafeBinder(binder) => { + let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut(); + generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); + vis.visit_ty(inner_ty); + } TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)), TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Pat(ty, pat) => { diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 1a80a9ccdbf54..fb066093651fd 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -251,6 +251,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { ty = &mut_ty.ty; } + ast::TyKind::UnsafeBinder(binder) => { + ty = &binder.inner_ty; + } + ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output { ast::FnRetTy::Default(_) => break None, ast::FnRetTy::Ty(ret) => ty = ret, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 9f9c3d8c39239..0561b65b4301f 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -512,6 +512,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { walk_list!(visitor, visit_generic_param, generic_params); try_visit!(walk_fn_decl(visitor, decl)); } + TyKind::UnsafeBinder(binder) => { + walk_list!(visitor, visit_generic_param, &binder.generic_params); + try_visit!(visitor.visit_ty(&binder.inner_ty)); + } TyKind::Path(maybe_qself, path) => { try_visit!(walk_qself(visitor, maybe_qself)); try_visit!(visitor.visit_path(path, *id)); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7e07ccf28a0cb..cc0d4b0435da7 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1190,6 +1190,14 @@ impl<'a> State<'a> { ast::TyKind::BareFn(f) => { self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params); } + ast::TyKind::UnsafeBinder(f) => { + self.ibox(INDENT_UNIT); + self.word("unsafe"); + self.print_generic_params(&f.generic_params); + self.nbsp(); + self.print_type(&f.inner_ty); + self.end(); + } ast::TyKind::Path(None, path) => { self.print_path(path, false, 0); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a8ed8b5df9c00..642f7333e8680 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -5,6 +5,7 @@ use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, + UnsafeBinderTy, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; @@ -361,6 +362,8 @@ impl<'a> Parser<'a> { TyKind::Err(guar) } } + } else if self.check_keyword(kw::Unsafe) { + self.parse_unsafe_binder_ty()? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(self.token.span, msg); @@ -382,6 +385,15 @@ impl<'a> Parser<'a> { if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } + fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> { + assert!(self.eat_keyword(kw::Unsafe)); + self.expect_lt()?; + let generic_params = self.parse_generic_params()?; + self.expect_gt()?; + + Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty: self.parse_ty()? }))) + } + /// Parse an anonymous struct or union (only for field definitions): /// ```ignore (feature-not-ready) /// #[repr(C)] From 888211f6e43359593ac96e328d0caa717d6f1214 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 30 Aug 2024 17:03:14 -0400 Subject: [PATCH 2/8] Lower AST and resolve lifetimes for unsafe binder type --- compiler/rustc_ast_lowering/src/index.rs | 6 ++++ compiler/rustc_ast_lowering/src/lib.rs | 9 ++++++ .../src/lifetime_collector.rs | 5 ++++ compiler/rustc_hir/src/hir.rs | 12 ++++++++ compiler/rustc_hir/src/intravisit.rs | 5 ++++ .../src/collect/generics_of.rs | 6 ++++ .../src/collect/resolve_bound_vars.rs | 29 +++++++++++++++++++ .../src/hir_ty_lowering/mod.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 13 +++++++++ compiler/rustc_lint/src/non_local_def.rs | 2 ++ compiler/rustc_middle/src/hir/map/mod.rs | 2 ++ compiler/rustc_passes/src/hir_stats.rs | 2 ++ compiler/rustc_resolve/src/late.rs | 22 ++++++++++++++ 13 files changed, 114 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index e77c0fb3a3ed3..26b8472ac740e 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -285,6 +285,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.insert(ty.span, ty.hir_id, Node::Ty(ty)); self.with_parent(ty.hir_id, |this| { + // FIXME(unsafe_binders): Should we split this out into a separate + // visit function? + if let TyKind::UnsafeBinder(binder) = ty.kind { + this.insert(ty.span, binder.hir_id, Node::UnsafeBinder(binder)); + }; + intravisit::walk_ty(this, ty); }); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c6cb7aa7dd5c2..1a45ccd44edeb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1332,6 +1332,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_names: self.lower_fn_params_to_names(&f.decl), })) } + TyKind::UnsafeBinder(f) => { + let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); + hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy { + span: self.lower_span(t.span), + hir_id: self.next_id(), + generic_params, + inner_ty: self.lower_ty(&f.inner_ty, itctx), + })) + } TyKind::Never => hir::TyKind::Never, TyKind::Tup(tys) => hir::TyKind::Tup( self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 1e82ba5db8a2a..b993413d8a1b3 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -95,6 +95,11 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { visit::walk_ty(self, t); self.current_binders.pop(); } + TyKind::UnsafeBinder(_) => { + self.current_binders.push(t.id); + visit::walk_ty(self, t); + self.current_binders.pop(); + } TyKind::Ref(None, _) => { self.record_elided_anchor(t.id, t.span); visit::walk_ty(self, t); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 71216023ecc33..f9cc209b8728e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2747,6 +2747,14 @@ pub struct BareFnTy<'hir> { pub param_names: &'hir [Ident], } +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct UnsafeBinderTy<'hir> { + pub hir_id: HirId, + pub span: Span, + pub generic_params: &'hir [GenericParam<'hir>], + pub inner_ty: &'hir Ty<'hir>, +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct OpaqueTy<'hir> { pub generics: &'hir Generics<'hir>, @@ -2839,6 +2847,8 @@ pub enum TyKind<'hir> { Ref(&'hir Lifetime, MutTy<'hir>), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(&'hir BareFnTy<'hir>), + /// Uwu + UnsafeBinder(&'hir UnsafeBinderTy<'hir>), /// The never type (`!`). Never, /// A tuple (`(A, B, C, D, ...)`). @@ -3810,6 +3820,7 @@ pub enum Node<'hir> { // FIXME: Merge into `Node::Infer`. ArrayLenInfer(&'hir InferArg), PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), + UnsafeBinder(&'hir UnsafeBinderTy<'hir>), // Created by query feeding Synthetic, Err(Span), @@ -3862,6 +3873,7 @@ impl<'hir> Node<'hir> { | Node::Infer(..) | Node::WhereBoundPredicate(..) | Node::ArrayLenInfer(..) + | Node::UnsafeBinder(..) | Node::Synthetic | Node::Err(..) => None, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 4da3224578519..f55d0522da574 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -891,6 +891,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul walk_list!(visitor, visit_generic_param, function_declaration.generic_params); try_visit!(visitor.visit_fn_decl(function_declaration.decl)); } + TyKind::UnsafeBinder(ref unsafe_binder) => { + try_visit!(visitor.visit_id(unsafe_binder.hir_id)); + walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params); + try_visit!(visitor.visit_ty(unsafe_binder.inner_ty)); + } TyKind::Path(ref qpath) => { try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span)); } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 0a8eef2006d5a..760731a47cecd 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -480,6 +480,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option { + self.outer_index.shift_in(1); + let res = intravisit::walk_ty(self, ty); + self.outer_index.shift_out(1); + res + } _ => intravisit::walk_ty(self, ty), } } 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 c9b949ad88d54..34892ce3b3f90 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -648,6 +648,35 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { intravisit::walk_ty(this, ty); }); } + hir::TyKind::UnsafeBinder(binder) => { + let (mut bound_vars, binders): (FxIndexMap, Vec<_>) = + binder + .generic_params + .iter() + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); + (pair, r) + }) + .unzip(); + + deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types"); + + self.record_late_bound_vars(binder.hir_id, binders); + let scope = Scope::Binder { + hir_id: ty.hir_id, + bound_vars, + s: self.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: None, + }; + self.with(scope, |this| { + // a bare fn has no bounds, so everything + // contained within is scoped within its binder. + intravisit::walk_ty(this, ty); + }); + } hir::TyKind::TraitObject(bounds, lifetime, _) => { debug!(?bounds, ?lifetime, "TraitObject"); let scope = Scope::TraitRefBoundary { s: self.scope }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e95b5142559f4..87a9907ca3ea0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2062,6 +2062,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)), ) } + hir::TyKind::UnsafeBinder(_binder) => todo!(), hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.prohibit_or_lint_bare_trait_object_ty(hir_ty); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1c52283d537d3..cd9943acbdce2 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -123,6 +123,7 @@ impl<'a> State<'a> { self.print_bounds(":", pred.bounds); } Node::ArrayLenInfer(_) => self.word("_"), + Node::UnsafeBinder(binder) => self.print_unsafe_binder(binder), Node::Synthetic => unreachable!(), Node::Err(_) => self.word("/*ERROR*/"), } @@ -293,6 +294,9 @@ impl<'a> State<'a> { hir::TyKind::BareFn(f) => { self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names); } + hir::TyKind::UnsafeBinder(unsafe_binder) => { + self.print_unsafe_binder(unsafe_binder); + } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, lifetime, syntax) => { @@ -348,6 +352,15 @@ impl<'a> State<'a> { self.end() } + fn print_unsafe_binder(&mut self, unsafe_binder: &hir::UnsafeBinderTy<'_>) { + self.ibox(INDENT_UNIT); + self.word("unsafe"); + self.print_generic_params(unsafe_binder.generic_params); + self.nbsp(); + self.print_type(unsafe_binder.inner_ty); + self.end(); + } + fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index ef7ab7efd5444..80d31af2a0adb 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -436,6 +436,8 @@ fn ty_has_local_parent( | TyKind::Ptr(_) | TyKind::Ref(_, _) | TyKind::BareFn(_) + // FIXME(unsafe_binders): Do we want to consider this local? + | TyKind::UnsafeBinder(_) | TyKind::Never | TyKind::Tup(_) | TyKind::Path(_) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 167b5aef68b7a..2775bc45b38b4 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -933,6 +933,7 @@ impl<'hir> Map<'hir> { Node::WhereBoundPredicate(pred) => pred.span, Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, + Node::UnsafeBinder(binder) => binder.span, Node::Synthetic => unreachable!(), Node::Err(span) => span, } @@ -1215,6 +1216,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::Synthetic => unreachable!(), Node::Err(_) => node_str("error"), Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), + Node::UnsafeBinder(_) => node_str("unsafe binder"), } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 903fb1147440c..0ae73fa7c324c 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -329,6 +329,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Ptr, Ref, BareFn, + UnsafeBinder, Never, Tup, AnonAdt, @@ -581,6 +582,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Ptr, Ref, BareFn, + UnsafeBinder, Never, Tup, AnonStruct, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 66c1ff93ce1ce..f610accc9fdb5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -886,6 +886,28 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r }, ) } + TyKind::UnsafeBinder(unsafe_binder) => { + // FIXME(unsafe_binder): Better span + let span = ty.span; + self.with_generic_param_rib( + &unsafe_binder.generic_params, + RibKind::Normal, + LifetimeRibKind::Generics { + binder: ty.id, + kind: LifetimeBinderKind::BareFnType, + span, + }, + |this| { + this.visit_generic_params(&unsafe_binder.generic_params, false); + this.with_lifetime_rib( + // We don't allow anonymous `unsafe &'_ ()` binders, + // although I guess we could. + LifetimeRibKind::AnonymousReportError, + |this| this.visit_ty(&unsafe_binder.inner_ty), + ); + }, + ) + } TyKind::Array(element_ty, length) => { self.visit_ty(element_ty); self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No)); From 29fa3253cbc07b5d7e45484cf9b11f7ba896ba88 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 30 Aug 2024 17:14:54 -0400 Subject: [PATCH 3/8] Initial work on the type system layer --- compiler/rustc_borrowck/src/lib.rs | 2 + .../src/debuginfo/type_names.rs | 1 + .../src/const_eval/valtrees.rs | 8 ++- .../src/interpret/intrinsics.rs | 1 + .../rustc_const_eval/src/interpret/stack.rs | 2 + .../src/interpret/validity.rs | 1 + .../rustc_const_eval/src/util/type_name.rs | 3 +- .../src/coherence/inherent_impls.rs | 3 +- .../src/coherence/orphan.rs | 3 +- .../src/hir_ty_lowering/mod.rs | 8 ++- .../src/variance/constraints.rs | 5 ++ compiler/rustc_hir_typeck/src/cast.rs | 2 + .../src/infer/canonical/canonicalizer.rs | 1 + compiler/rustc_lint/src/types.rs | 2 + compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/error.rs | 1 + compiler/rustc_middle/src/ty/flags.rs | 6 ++ compiler/rustc_middle/src/ty/layout.rs | 5 ++ compiler/rustc_middle/src/ty/print/mod.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 3 + .../rustc_middle/src/ty/structural_impls.rs | 2 + compiler/rustc_middle/src/ty/sty.rs | 18 ++++- compiler/rustc_middle/src/ty/util.rs | 13 +++- compiler/rustc_middle/src/ty/walk.rs | 3 + .../src/move_paths/builder.rs | 2 + .../src/dataflow_const_prop.rs | 3 +- .../src/canonicalizer.rs | 1 + .../rustc_next_trait_solver/src/coherence.rs | 4 +- .../src/solve/assembly/mod.rs | 2 + .../src/solve/assembly/structural_traits.rs | 8 +++ .../src/solve/normalizes_to/mod.rs | 15 ++++ .../src/solve/trait_goals.rs | 3 +- compiler/rustc_pattern_analysis/src/rustc.rs | 1 + compiler/rustc_privacy/src/lib.rs | 1 + .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 5 ++ .../cfi/typeid/itanium_cxx_abi/transform.rs | 3 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 2 + compiler/rustc_symbol_mangling/src/v0.rs | 3 + .../traits/fulfillment_errors.rs | 1 + .../src/traits/project.rs | 5 ++ .../src/traits/query/dropck_outlives.rs | 8 ++- .../src/traits/select/candidate_assembly.rs | 22 ++++-- .../src/traits/select/confirmation.rs | 2 + .../src/traits/select/mod.rs | 10 +++ .../rustc_trait_selection/src/traits/wf.rs | 3 + compiler/rustc_ty_utils/src/layout.rs | 5 ++ compiler/rustc_ty_utils/src/needs_drop.rs | 5 ++ compiler/rustc_ty_utils/src/ty.rs | 2 + compiler/rustc_type_ir/src/binder.rs | 8 +-- compiler/rustc_type_ir/src/fast_reject.rs | 11 ++- compiler/rustc_type_ir/src/inherent.rs | 3 + compiler/rustc_type_ir/src/outlives.rs | 1 + compiler/rustc_type_ir/src/relate.rs | 4 ++ compiler/rustc_type_ir/src/ty_kind.rs | 72 ++++++++++++++++++- 54 files changed, 284 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 733fabe557e6b..eed5838e46793 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1634,6 +1634,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) @@ -1679,6 +1680,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 369ab387bea58..5345f5d18ab97 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -435,6 +435,7 @@ fn push_debuginfo_type_name<'tcx>( push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited); } } + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), // Type parameters from polymorphized functions. ty::Param(_) => { write!(output, "{t:?}").unwrap(); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index a11d491bdd2c9..8253aaaf1400e 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -178,7 +178,8 @@ fn const_to_valtree_inner<'tcx>( | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) - | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType(ty)), + | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)), } } @@ -356,7 +357,10 @@ pub fn valtree_to_const_value<'tcx>( | ty::FnPtr(..) | ty::Str | ty::Slice(_) - | ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), + | ty::Dynamic(..) + | ty::UnsafeBinder(_) => { + bug!("no ValTree should have been created for type {:?}", ty.kind()) + } } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e1fd8bea1f30c..9fba679608457 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -87,6 +87,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) | ty::Never | ty::Tuple(_) | ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 15868f1b02d92..a07f899992c6b 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -505,6 +505,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We don't want to do any queries, so there is not much we can do with ADTs. ty::Adt(..) => false, + ty::UnsafeBinder(_) => false, + ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false, ty::Infer(ty::TyVar(_)) => false, diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ff3c6120f0cac..47dcbb6decf64 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -760,6 +760,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // Nothing to check. Ok(true) } + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), // The above should be all the primitive types. The rest is compound, we // check them by visiting their fields/variants. ty::Adt(..) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 36c7bed5c1194..e14cd603c5828 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -38,7 +38,8 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::FnPtr(..) | ty::Never | ty::Tuple(_) - | ty::Dynamic(_, _, _) => self.pretty_print_type(ty), + | ty::Dynamic(_, _, _) + | ty::UnsafeBinder(_) => self.pretty_print_type(ty), // Placeholders (all printed as `_` to uniformize them). ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => { diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index c07d8009aa56c..d1b868ab159e0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -177,7 +177,8 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Ref(..) | ty::Never | ty::FnPtr(..) - | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), + | ty::Tuple(..) + | ty::UnsafeBinder(_) => self.check_primitive_impl(id, self_ty), ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) | ty::Param(_) => { Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span })) } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 5fdaba41fb262..23fd9ddffe03f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -225,7 +225,8 @@ pub(crate) fn orphan_check_impl( | ty::FnDef(..) | ty::FnPtr(..) | ty::Never - | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), + | ty::Tuple(..) + | ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 87a9907ca3ea0..921207749b886 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2062,7 +2062,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)), ) } - hir::TyKind::UnsafeBinder(_binder) => todo!(), + hir::TyKind::UnsafeBinder(binder) => Ty::new_unsafe_binder( + tcx, + ty::Binder::bind_with_vars( + self.lower_ty(binder.inner_ty), + tcx.late_bound_vars(binder.hir_id), + ), + ), hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.prohibit_or_lint_bare_trait_object_ty(hir_ty); diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 415b23d812b5f..df82a93f93d5b 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -322,6 +322,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_sig(current, sig_tys.with(hdr), variance); } + ty::UnsafeBinder(ty) => { + let invariant = self.invariant(variance); + self.add_constraints_from_ty(current, ty.skip_binder(), invariant); + } + ty::Error(_) => { // we encounter this when walking the trait references for object // types, where we use Error as the Self type diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index aab0c4c116afe..22945287ec3eb 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -115,6 +115,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(&f) => self.pointer_kind(f, span)?, }, + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + // Pointers to foreign types are thin, despite being unsized ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 35ea42338250d..2b13c8836d104 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -441,6 +441,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Dynamic(..) + | ty::UnsafeBinder(_) | ty::Never | ty::Tuple(..) | ty::Alias(..) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f5a24f9808d2a..5414da458eaa0 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1154,6 +1154,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + ty::Param(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Infer(..) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f017216489d0c..028ccf01c8604 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -426,7 +426,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::Never - | ty::Tuple(_) => { + | ty::Tuple(_) + | ty::UnsafeBinder(_) => { let simp = ty::fast_reject::simplify_type( tcx, self_ty, @@ -2264,6 +2265,7 @@ impl<'tcx> TyCtxt<'tcx> { Ref, FnDef, FnPtr, + UnsafeBinder, Placeholder, Coroutine, CoroutineWitness, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index b02eff3bfd6a3..94e1d7b182f29 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -195,6 +195,7 @@ impl<'tcx> Ty<'tcx> { _ => "fn item".into(), }, ty::FnPtr(..) => "fn pointer".into(), + ty::UnsafeBinder(_) => "unsafe binder".into(), ty::Dynamic(..) => "trait object".into(), ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(), ty::Coroutine(def_id, ..) => { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index fc079592583e6..72a4eae0aa115 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -253,6 +253,12 @@ impl FlagComputation { &ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| { computation.add_tys(sig_tys.inputs_and_output); }), + + &ty::UnsafeBinder(bound_ty) => { + self.bound_computation(bound_ty.into(), |computation, ty| { + computation.add_ty(ty); + }) + } } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cf0c29e0c8c39..9adf9a7555f72 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -785,6 +785,11 @@ where bug!("TyAndLayout::field({:?}): not applicable", this) } + ty::UnsafeBinder(bound_ty) => { + let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i) + } + // Potentially-fat pointers. ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { assert!(i < this.fields.count()); diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index cc7467467603a..b0150bc11920b 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -291,6 +291,7 @@ fn characteristic_def_id_of_type_cached<'a>( | ty::Uint(_) | ty::Str | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Alias(..) | ty::Placeholder(..) | ty::Param(_) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5b4ee2791f8dd..f6e1d0efd7196 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -697,6 +697,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))), + ty::UnsafeBinder(ref bound_ty) => { + self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?; + } ty::Infer(infer_ty) => { if self.should_print_verbose() { p!(write("{:?}", ty.kind())); diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index cd9ff9b60d859..2aae6abae56e0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -375,6 +375,7 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr), + ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?), ty::Ref(r, ty, mutbl) => { ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } @@ -425,6 +426,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor), ty::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor), + ty::UnsafeBinder(ref f) => f.visit_with(visitor), ty::Ref(r, ty, _) => { try_visit!(r.visit_with(visitor)); ty.visit_with(visitor) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index db9978a7f5334..be48436a7937b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -662,6 +662,11 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, FnPtr(sig_tys, hdr)) } + #[inline] + pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> { + Ty::new(tcx, UnsafeBinder(b.into())) + } + #[inline] pub fn new_dynamic( tcx: TyCtxt<'tcx>, @@ -951,6 +956,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_pat(interner, ty, pat) } + fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self { + Ty::new_unsafe_binder(interner, ty) + } + fn new_unit(interner: TyCtxt<'tcx>) -> Self { interner.types.unit } @@ -1459,6 +1468,7 @@ impl<'tcx> Ty<'tcx> { | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) + | ty::UnsafeBinder(_) | ty::Error(_) | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8, @@ -1638,6 +1648,8 @@ impl<'tcx> Ty<'tcx> { // metadata of `tail`. ty::Param(_) | ty::Alias(..) => Err(tail), + | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + ty::Infer(ty::TyVar(_)) | ty::Pat(..) | ty::Bound(..) @@ -1798,6 +1810,7 @@ impl<'tcx> Ty<'tcx> { | ty::Float(_) | ty::FnDef(..) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::RawPtr(..) | ty::Char | ty::Ref(..) @@ -1877,6 +1890,8 @@ impl<'tcx> Ty<'tcx> { // Might be, but not "trivial" so just giving the safe answer. ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false, + ty::UnsafeBinder(_) => false, + // Needs normalization or revealing to determine, so no is the safe answer. ty::Alias(..) => false, @@ -1954,7 +1969,8 @@ impl<'tcx> Ty<'tcx> { | Coroutine(_, _) | CoroutineWitness(..) | Never - | Tuple(_) => true, + | Tuple(_) + | UnsafeBinder(_) => true, Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 321b51289fb08..091900417df1e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1286,6 +1286,7 @@ impl<'tcx> Ty<'tcx> { | ty::Foreign(_) | ty::Coroutine(..) | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1326,6 +1327,7 @@ impl<'tcx> Ty<'tcx> { | ty::Foreign(_) | ty::Coroutine(..) | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1358,6 +1360,9 @@ impl<'tcx> Ty<'tcx> { | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => AsyncDropGlueMorphology::Noop, + // FIXME(unsafe_binders): + ty::UnsafeBinder(_) => todo!(), + ty::Tuple(tys) if tys.is_empty() => AsyncDropGlueMorphology::Noop, ty::Adt(adt_def, _) if adt_def.is_manually_drop() => AsyncDropGlueMorphology::Noop, @@ -1559,7 +1564,7 @@ impl<'tcx> Ty<'tcx> { false } - ty::Foreign(_) | ty::CoroutineWitness(..) | ty::Error(_) => false, + ty::Foreign(_) | ty::CoroutineWitness(..) | ty::Error(_) | ty::UnsafeBinder(_) => false, } } @@ -1718,7 +1723,8 @@ pub fn needs_drop_components_with_async<'tcx>( | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) - | ty::CoroutineWitness(..) => Ok(smallvec![ty]), + | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) => Ok(smallvec![ty]), } } @@ -1753,7 +1759,8 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) - | ty::Adt(..) => false, + | ty::Adt(..) + | ty::UnsafeBinder(_) => false, ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => is_trivially_const_drop(ty), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index a93a146ec7c42..2dcba8c2f82c4 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -194,6 +194,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()), ); } + ty::UnsafeBinder(bound_ty) => { + stack.push(bound_ty.skip_binder().into()); + } }, GenericArgKind::Lifetime(_) => {} GenericArgKind::Const(parent_ct) => match parent_ct.kind() { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 3c8be2f73e14a..8522465ff4a44 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -161,6 +161,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(..) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -204,6 +205,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 2026b7893159e..06f77725d2969 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -712,7 +712,8 @@ fn try_write_constant<'tcx>( | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) - | ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"), + | ty::Dynamic(..) + | ty::UnsafeBinder(_) => throw_machine_stop_str!("unsupported type"), ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 196ddeb244302..a61616087dd0e 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -359,6 +359,7 @@ impl, I: Interner> TypeFolder for Canonicaliz | ty::Pat(_, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 2461ef0c0df57..408742747c2a1 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -339,7 +339,9 @@ where | ty::Slice(..) | ty::RawPtr(..) | ty::Never - | ty::Tuple(..) => self.found_non_local_ty(ty), + | ty::Tuple(..) + // FIXME(unsafe_binders): Non-local? + | ty::UnsafeBinder(_) => self.found_non_local_ty(ty), ty::Param(..) => panic!("unexpected ty param"), diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 520afbeb645c2..5c84901284bad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -536,6 +536,7 @@ where | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -623,6 +624,7 @@ where | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Alias(..) | ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 5c1a7852dc0b4..5b79916faca64 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -83,6 +83,8 @@ where .map(|bty| bty.instantiate(cx, args)) .collect()), + ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]), + // For `PhantomData`, we pass `T`. ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), @@ -144,6 +146,8 @@ where panic!("unexpected type `{ty:?}`") } + ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]), + // impl Sized for () // impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1 ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])), @@ -239,6 +243,8 @@ where } }, + ty::UnsafeBinder(_) => Err(NoSolution), + // impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types ty::CoroutineWitness(def_id, args) => Ok(ecx .cx() @@ -374,6 +380,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable Ty::new_projection(cx, metadata_def_id, [tail_ty]), }, + ty::UnsafeBinder(_) => { + // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders. + todo!() + } + ty::Infer( ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_), ) @@ -771,6 +776,11 @@ where | ty::Tuple(_) | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()), + ty::UnsafeBinder(_) => { + // FIXME(unsafe_binders): instantiate this with placeholders?? i guess?? + todo!("discr subgoal...") + } + // We do not call `Ty::discriminant_ty` on alias, param, or placeholder // types, which return `::Discriminant` // (or ICE in the case of placeholders). Projecting a type to itself @@ -818,6 +828,11 @@ where | ty::Tuple(_) | ty::Error(_) => self_ty.async_destructor_ty(ecx.cx()), + ty::UnsafeBinder(_) => { + // FIXME(unsafe_binders): Instantiate the binder with placeholders I guess. + todo!() + } + // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder // types, which return `::AsyncDestructor` // (or ICE in the case of placeholders). Projecting a type to itself diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 781ca127e151e..d508a23c9b5cd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1151,7 +1151,8 @@ where | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) - | ty::Adt(_, _) => { + | ty::Adt(_, _) + | ty::UnsafeBinder(_) => { let mut disqualifying_impl = None; self.cx().for_each_relevant_impl( goal.predicate.def_id(), diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 72737fb98cbf7..bfd17a1461740 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -413,6 +413,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) + | ty::UnsafeBinder(_) | ty::Alias(_, _) | ty::Param(_) | ty::Error(_) => ConstructorSet::Unlistable, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9094b00fbfb44..97dc42765d816 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -282,6 +282,7 @@ where | ty::Ref(..) | ty::Pat(..) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Param(..) | ty::Bound(..) | ty::Error(_) diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 320d66163848f..92769c91ddfbc 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -618,6 +618,11 @@ pub fn encode_ty<'tcx>( typeid.push_str(&s); } + // FIXME(unsafe_binders): Implement this. + ty::UnsafeBinder(_) => { + todo!() + } + // Trait types ty::Dynamic(predicates, region, kind) => { // u3dynIE, where is , as diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 80a9ba79c2851..5b0f8d53b6645 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -64,7 +64,8 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { | ty::Pat(..) | ty::Slice(..) | ty::Str - | ty::Tuple(..) => t.super_fold_with(self), + | ty::Tuple(..) + | ty::UnsafeBinder(_) => t.super_fold_with(self), ty::Bool => { if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index e54ab1f7e24c3..160fb24785ebc 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -355,6 +355,8 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::FnPtr(sig_tys, hdr) => { TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables))) } + // FIXME(unsafe_binders): + ty::UnsafeBinder(_) => todo!(), ty::Dynamic(existential_predicates, region, dyn_kind) => { TyKind::RigidTy(RigidTy::Dynamic( existential_predicates diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index f3da7ff1ca7b0..fbbc9af557967 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -467,6 +467,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { })?; } + // FIXME(unsafe_binder): + ty::UnsafeBinder(..) => todo!(), + ty::Dynamic(predicates, r, kind) => { self.push(match kind { ty::Dyn => "D", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 19e2679ae4da7..008eb5d915311 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1488,6 +1488,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::CoroutineWitness(..) => Some(20), ty::CoroutineClosure(..) => Some(21), ty::Pat(..) => Some(22), + ty::UnsafeBinder(..) => Some(23), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9cd99d99fc3c3..33f749eeb58c5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1072,6 +1072,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats always have `u8` as their discriminant. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + // type parameters, opaques, and unnormalized projections don't have // a known discriminant and may need to be normalized further or rely // on param env for discriminant projections @@ -1097,6 +1099,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1188,6 +1191,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( true } + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + // FIXME(compiler-errors): are Bound and Placeholder types ever known sized? ty::Param(_) | ty::Alias(..) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index c70fe13fc69a2..e78c134d4e812 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -82,7 +82,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Placeholder(..) | ty::Infer(_) | ty::Bound(..) - | ty::Coroutine(..) => false, + | ty::Coroutine(..) + | ty::UnsafeBinder(_) => false, } } @@ -328,6 +329,11 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( constraints.dtorck_types.push(ty); } + // Can't instantiate binder here. + ty::UnsafeBinder(_) => { + constraints.dtorck_types.push(ty); + } + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => { // By the time this code runs, all type variables ought to // be fully resolved. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e5f1d5c36daf6..dff1698730c1c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -654,7 +654,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { continue; } - match obligation.self_ty().skip_binder().kind() { + let self_ty = obligation.self_ty().skip_binder(); + match self_ty.kind() { // Fast path to avoid evaluating an obligation that trivially holds. // There may be more bounds, but these are checked by the regular path. ty::FnPtr(..) => return false, @@ -667,6 +668,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Param(..) | ty::Bound(_, _) => {} + // FIXME: Function definitions could actually implement `FnPtr` by + // casting the ZST function def to a function pointer. + ty::FnDef(_, _) => return true, // These can't possibly implement `FnPtr` as they are concrete types // and not `FnPtr` ty::Bool @@ -686,12 +690,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) | ty::Never | ty::Tuple(_) - | ty::Error(_) => return true, - // FIXME: Function definitions could actually implement `FnPtr` by - // casting the ZST function def to a function pointer. - ty::FnDef(_, _) => return true, + | ty::Error(_) => { + debug_assert!(self_ty.is_known_rigid()); + return true; + } } // Generic params can implement `FnPtr` if the predicate @@ -829,7 +834,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Coroutine(..) | ty::Never | ty::Tuple(_) - | ty::CoroutineWitness(..) => { + | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) => { // Only consider auto impls if there are no manual impls for the root of `self_ty`. // // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl @@ -1200,6 +1206,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // not structurally... so don't push a candidate. } + ty::UnsafeBinder(_) => todo!(), + ty::Bool | ty::Char | ty::Int(_) @@ -1295,6 +1303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnDef(_, _) | ty::Pat(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1364,6 +1373,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) + | ty::UnsafeBinder(_) | ty::Never | ty::Tuple(..) | ty::Alias(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index d15acd51c86e3..8ece1000370f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1413,6 +1413,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) => {} + ty::UnsafeBinder(_) => todo!(), + // `ManuallyDrop` is trivially drop ty::Adt(def, _) if def.is_manually_drop() => {} diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cbc17a058f6d1..c46ff7d8e917f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2145,6 +2145,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } + // FIXME(unsafe_binders): This binder needs to be squashed + ty::UnsafeBinder(binder_ty) => Where(binder_ty.map_bound(|ty| vec![ty])), + ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, @@ -2183,6 +2186,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> { None } + // FIXME(unsafe_binder): Should we conditionally + // (i.e. universally) implement copy/clone? + ty::UnsafeBinder(_) => todo!(), + ty::Dynamic(..) | ty::Str | ty::Slice(..) @@ -2335,6 +2342,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Never | ty::Char => ty::Binder::dummy(Vec::new()), + // TODO: binder needs opening + ty::UnsafeBinder(_) => todo!(), + // Treat this like `struct str([u8]);` ty::Str => ty::Binder::dummy(vec![Ty::new_slice(self.tcx(), self.tcx().types.u8)]), diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 354f3034b8ac5..887469e33ed21 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -817,6 +817,9 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // Let the visitor iterate into the argument/return // types appearing in the fn signature. } + ty::UnsafeBinder(_) => { + // We should also recurse into the binder here. + } ty::Dynamic(data, r, _) => { // WfObject diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 34c9f1b63c066..2a394c56263dc 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -653,6 +653,11 @@ fn layout_of_uncached<'tcx>( tcx.mk_layout(layout) } + ty::UnsafeBinder(bound_ty) => { + let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + cx.layout_of(ty)?.layout + } + // Types with no meaningful known layout. ty::Alias(..) => { // NOTE(eddyb) `layout_of` query should've normalized these away, diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 5fecbd310b770..008ce44c5e520 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -180,6 +180,11 @@ where } } + ty::UnsafeBinder(bound_ty) => { + let ty = self.tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + queue_type(self, ty); + } + _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, args) => { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 28a81b1b06217..48d59ed610248 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -37,6 +37,8 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option None, + UnsafeBinder(_) => todo!(), + // these are never sized Str | Slice(..) | Dynamic(_, _, ty::Dyn) | Foreign(..) => Some(ty), diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index f20beb797500e..b2d6ae7e66cc9 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -6,8 +6,6 @@ use std::ops::{ControlFlow, Deref}; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; -#[cfg(feature = "nightly")] -use rustc_serialize::Decodable; use tracing::instrument; use crate::data_structures::SsoHashSet; @@ -69,14 +67,14 @@ macro_rules! impl_binder_encode_decode { self.as_ref().skip_binder().encode(e); } } - impl> Decodable for ty::Binder + impl> rustc_serialize::Decodable for ty::Binder where $t: TypeVisitable + rustc_serialize::Decodable, I::BoundVarKinds: rustc_serialize::Decodable, { fn decode(decoder: &mut D) -> Self { - let bound_vars = Decodable::decode(decoder); - ty::Binder::bind_with_vars(<$t>::decode(decoder), bound_vars) + let bound_vars = rustc_serialize::Decodable::decode(decoder); + ty::Binder::bind_with_vars(rustc_serialize::Decodable::decode(decoder), bound_vars) } } )* diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 2c8e47bcbca2a..90fb3f3d47bd9 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -138,6 +138,7 @@ pub fn simplify_type( ty::FnPtr(sig_tys, _hdr) => { Some(SimplifiedType::Function(sig_tys.skip_binder().inputs().len())) } + ty::UnsafeBinder(binder) => simplify_type(cx, binder.skip_binder(), treat_params), ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { TreatParams::AsRigid => Some(SimplifiedType::Placeholder), @@ -270,7 +271,8 @@ impl {} + | ty::Placeholder(_) + | ty::UnsafeBinder(_) => {} }; // For purely rigid types, use structural equivalence. @@ -413,6 +415,13 @@ impl match rhs.kind() { + ty::UnsafeBinder(rhs_ty) => { + self.types_may_unify(lhs_ty.skip_binder(), rhs_ty.skip_binder()) + } + _ => false, + }, + ty::Error(..) => true, } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 59a83ea5412d5..6626cc8f71bc8 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -112,6 +112,8 @@ pub trait Ty>: fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; + fn new_unsafe_binder(interner: I, ty: ty::Binder) -> Self; + fn tuple_fields(self) -> I::Tys; fn to_opt_closure_kind(self) -> Option; @@ -182,6 +184,7 @@ pub trait Ty>: | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index ac35215fbaa0d..9aabd29756864 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -190,6 +190,7 @@ impl TypeVisitor for OutlivesCollector<'_, I> { | ty::RawPtr(_, _) | ty::Ref(_, _, _) | ty::FnPtr(..) + | ty::UnsafeBinder(_) | ty::Dynamic(_, _, _) | ty::Tuple(_) => { ty.super_visit_with(self); diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 9c725f34d8e5b..5ef71477fea83 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -542,6 +542,10 @@ pub fn structurally_relate_tys>( Ok(Ty::new_pat(cx, ty, pat)) } + (ty::UnsafeBinder(a_binder), ty::UnsafeBinder(b_binder)) => { + Ok(Ty::new_unsafe_binder(cx, relation.binders(*a_binder, *b_binder)?)) + } + _ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))), } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index b7f6ef4ffbb9a..d63689c786ac8 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::ops::Deref; use derive_where::derive_where; use rustc_ast_ir::Mutability; @@ -8,12 +9,15 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +#[cfg(feature = "nightly")] +use rustc_serialize::Decodable; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use self::TyKind::*; pub use self::closure::*; use crate::inherent::*; -use crate::{self as ty, DebruijnIndex, Interner}; +use crate::visit::TypeVisitable; +use crate::{self as ty, DebruijnIndex, Interner, TyDecoder, TyEncoder}; mod closure; @@ -150,6 +154,13 @@ pub enum TyKind { /// worth the mild inconvenience. FnPtr(ty::Binder>, FnHeader), + /// An unsafe binder type. + /// + /// A higher-ranked type used to represent a type which has had some of its + /// lifetimes erased. This can be used to represent types in positions where + /// a lifetime is literally inexpressible, such as self-referential types. + UnsafeBinder(UnsafeBinderInner), + /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), @@ -287,6 +298,8 @@ impl fmt::Debug for TyKind { Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t), FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(), FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)), + // FIXME(unsafe_binder): print this like `unsafe<'a> T<'a>`. + UnsafeBinder(binder) => write!(f, "{:?}", binder), Dynamic(p, r, repr) => match repr { DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"), DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"), @@ -960,6 +973,63 @@ impl fmt::Debug for FnSig { } } +// FIXME: this is a distinct type because we need to define `Encode`/`Decode` +// impls in this crate for `Binder`. +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct UnsafeBinderInner(ty::Binder); + +impl From> for UnsafeBinderInner { + fn from(value: ty::Binder) -> Self { + UnsafeBinderInner(value) + } +} + +impl From> for ty::Binder { + fn from(value: UnsafeBinderInner) -> Self { + value.0 + } +} + +impl fmt::Debug for UnsafeBinderInner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Deref for UnsafeBinderInner { + type Target = ty::Binder; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[cfg(feature = "nightly")] +impl> rustc_serialize::Encodable for UnsafeBinderInner +where + I::Ty: rustc_serialize::Encodable, + I::BoundVarKinds: rustc_serialize::Encodable, +{ + fn encode(&self, e: &mut E) { + self.bound_vars().encode(e); + self.as_ref().skip_binder().encode(e); + } +} + +#[cfg(feature = "nightly")] +impl> rustc_serialize::Decodable for UnsafeBinderInner +where + I::Ty: TypeVisitable + rustc_serialize::Decodable, + I::BoundVarKinds: rustc_serialize::Decodable, +{ + fn decode(decoder: &mut D) -> Self { + let bound_vars = Decodable::decode(decoder); + UnsafeBinderInner(ty::Binder::bind_with_vars(Decodable::decode(decoder), bound_vars)) + } +} + // This is just a `FnSig` without the `FnHeader` fields. #[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] From ce76ef36e73d6d57a8fcb203a836722efb7206cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 13 Sep 2024 14:00:10 -0400 Subject: [PATCH 4/8] Add unwrap_unsafe_binder and wrap_unsafe_binder macro operators --- compiler/rustc_ast/src/ast.rs | 21 +++++- compiler/rustc_ast/src/mut_visit.rs | 6 ++ compiler/rustc_ast/src/util/classify.rs | 2 + compiler/rustc_ast/src/visit.rs | 4 + compiler/rustc_ast_lowering/src/expr.rs | 8 ++ .../rustc_ast_pretty/src/pprust/state/expr.rs | 19 +++++ .../src/assert/context.rs | 3 +- compiler/rustc_hir/src/hir.rs | 19 +++-- compiler/rustc_hir/src/intravisit.rs | 4 + compiler/rustc_hir_pretty/src/lib.rs | 13 ++++ compiler/rustc_hir_typeck/src/expr.rs | 74 ++++++++++++++++++- .../rustc_hir_typeck/src/expr_use_visitor.rs | 7 ++ compiler/rustc_lint/src/if_let_rescope.rs | 1 + .../rustc_lint/src/tail_expr_drop_order.rs | 1 + compiler/rustc_middle/src/thir.rs | 12 ++- compiler/rustc_middle/src/thir/visit.rs | 3 + .../src/build/expr/as_place.rs | 16 ++++ .../src/build/expr/as_rvalue.rs | 4 +- .../src/build/expr/category.rs | 4 +- .../rustc_mir_build/src/build/expr/into.rs | 4 +- .../rustc_mir_build/src/check_unsafety.rs | 2 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 11 +++ .../src/thir/pattern/check_match.rs | 4 +- compiler/rustc_mir_build/src/thir/print.rs | 14 ++++ compiler/rustc_parse/src/parser/expr.rs | 23 +++++- compiler/rustc_passes/src/hir_stats.rs | 39 +++++++++- compiler/rustc_passes/src/liveness.rs | 3 + compiler/rustc_passes/src/naked_functions.rs | 1 + compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_ty_utils/src/consts.rs | 5 ++ library/core/src/lib.rs | 2 + library/core/src/unsafe_binder.rs | 25 +++++++ 32 files changed, 337 insertions(+), 19 deletions(-) create mode 100644 library/core/src/unsafe_binder.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f4a0908c31473..28f155178b63c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1329,6 +1329,7 @@ impl Expr { | ExprKind::Type(..) | ExprKind::OffsetOf(..) | ExprKind::FormatArgs(..) + | ExprKind::UnsafeBinderCast(..) | ExprKind::MacCall(..) => ExprPrecedence::Mac, ExprKind::Err(_) | ExprKind::Dummy => ExprPrecedence::Err, } @@ -1455,7 +1456,13 @@ pub enum ExprKind { /// `'label: for await? pat in iter { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - ForLoop { pat: P, iter: P, body: P, label: Option