From b9c15c5d3bfb503676fffccab69fe27c5b532283 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Aug 2023 09:40:09 +0200 Subject: [PATCH 01/14] clarify safety documentation of ptr::swap and ptr::copy --- library/core/src/intrinsics.rs | 3 +++ library/core/src/ptr/mod.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 9ef2c7cde02eb..84b9a3bba88e3 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2709,6 +2709,9 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us /// /// * `dst` must be [valid] for writes of `count * size_of::()` bytes. /// +/// * `src` must remain valid for reads even after `dst` is written, and vice versa. +/// (In other words, there cannot be aliasing restrictions on the use of these pointers.) +/// /// * Both `src` and `dst` must be properly aligned. /// /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 5f094ac4e7e64..f8badc4130dca 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -797,6 +797,9 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// /// * Both `x` and `y` must be [valid] for both reads and writes. /// +/// * `x` must remain valid for reads and writes even after `y` is read/written, and vice versa. +/// (In other words, there cannot be aliasing restrictions on the use of these pointers.) +/// /// * Both `x` and `y` must be properly aligned. /// /// Note that even if `T` has size `0`, the pointers must be non-null and properly aligned. From 0188b9cbb43c2631111281fad0624f8bb0538e3a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 13:54:03 +0200 Subject: [PATCH 02/14] try to clarify wording --- library/core/src/intrinsics.rs | 11 ++++++----- library/core/src/ptr/mod.rs | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 84b9a3bba88e3..f7469008d7c00 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2705,12 +2705,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `src` must be [valid] for reads of `count * size_of::()` bytes. -/// -/// * `dst` must be [valid] for writes of `count * size_of::()` bytes. +/// * `src` must be [valid] for reads of `count * size_of::()` bytes, and must remain valid even +/// if `dst` is written for `count * size_of::()` bytes. (This means if the memory ranges +/// overlap, the two pointers must not be subject to aliasing restrictions relative to each +/// other.) /// -/// * `src` must remain valid for reads even after `dst` is written, and vice versa. -/// (In other words, there cannot be aliasing restrictions on the use of these pointers.) +/// * `dst` must be [valid] for writes of `count * size_of::()` bytes, and must remain valid even +/// if `src` is read for `count * size_of::()` bytes. /// /// * Both `src` and `dst` must be properly aligned. /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f8badc4130dca..69d775075f369 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -795,10 +795,9 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * Both `x` and `y` must be [valid] for both reads and writes. -/// -/// * `x` must remain valid for reads and writes even after `y` is read/written, and vice versa. -/// (In other words, there cannot be aliasing restrictions on the use of these pointers.) +/// * Both `x` and `y` must be [valid] for both reads and writes. They must remain valid even if the +/// other pointer is written. (This means if the memory ranges overlap, the two pointers must not +/// be subject to aliasing restrictions relative to each other.) /// /// * Both `x` and `y` must be properly aligned. /// From 56c17dc280c32112a9adf2cc69c845aa90d18dc4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 28 Aug 2023 10:30:48 +0100 Subject: [PATCH 03/14] Add tests for struct literals in if let/while let --- tests/ui/parser/struct-literal-in-if.rs | 5 +++++ tests/ui/parser/struct-literal-in-if.stderr | 18 +++++++++++++++++- tests/ui/parser/struct-literal-in-while.rs | 5 +++++ tests/ui/parser/struct-literal-in-while.stderr | 18 +++++++++++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/tests/ui/parser/struct-literal-in-if.rs b/tests/ui/parser/struct-literal-in-if.rs index 2ce2c8f189944..c4a253c3da25a 100644 --- a/tests/ui/parser/struct-literal-in-if.rs +++ b/tests/ui/parser/struct-literal-in-if.rs @@ -14,4 +14,9 @@ fn main() { }.hi() { println!("yo"); } + if let true = Foo { //~ ERROR struct literals are not allowed here + x: 3 + }.hi() { + println!("yo"); + } } diff --git a/tests/ui/parser/struct-literal-in-if.stderr b/tests/ui/parser/struct-literal-in-if.stderr index b5a9864bbc4c4..8b72469fcf582 100644 --- a/tests/ui/parser/struct-literal-in-if.stderr +++ b/tests/ui/parser/struct-literal-in-if.stderr @@ -14,5 +14,21 @@ LL | x: 3 LL ~ }).hi() { | -error: aborting due to previous error +error: struct literals are not allowed here + --> $DIR/struct-literal-in-if.rs:17:19 + | +LL | if let true = Foo { + | ___________________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ if let true = (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/struct-literal-in-while.rs b/tests/ui/parser/struct-literal-in-while.rs index 5000ce85b7f71..86931f7888dd8 100644 --- a/tests/ui/parser/struct-literal-in-while.rs +++ b/tests/ui/parser/struct-literal-in-while.rs @@ -14,4 +14,9 @@ fn main() { }.hi() { println!("yo"); } + while let true = Foo { //~ ERROR struct literals are not allowed here + x: 3 + }.hi() { + println!("yo"); + } } diff --git a/tests/ui/parser/struct-literal-in-while.stderr b/tests/ui/parser/struct-literal-in-while.stderr index 17e9277e07413..13d003608a1b0 100644 --- a/tests/ui/parser/struct-literal-in-while.stderr +++ b/tests/ui/parser/struct-literal-in-while.stderr @@ -14,5 +14,21 @@ LL | x: 3 LL ~ }).hi() { | -error: aborting due to previous error +error: struct literals are not allowed here + --> $DIR/struct-literal-in-while.rs:17:22 + | +LL | while let true = Foo { + | ______________________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ while let true = (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error: aborting due to 2 previous errors From 89235fd8379d6b1b0bcea704e162ba3d314906da Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 28 Aug 2023 10:31:45 +0100 Subject: [PATCH 04/14] Allow stuct literals in if let guards This is consistent with normal match guards. --- compiler/rustc_parse/src/parser/expr.rs | 4 +--- tests/ui/parser/struct-literal-in-match-guard.rs | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9ae3ef6172c73..5898c6565e6ef 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2477,9 +2477,7 @@ impl<'a> Parser<'a> { } else { self.expect(&token::Eq)?; } - let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { - this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into()) - })?; + let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())?; let span = lo.to(expr.span); self.sess.gated_spans.gate(sym::let_chains, span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span))) diff --git a/tests/ui/parser/struct-literal-in-match-guard.rs b/tests/ui/parser/struct-literal-in-match-guard.rs index bf0551b5c97b0..bbee60e281732 100644 --- a/tests/ui/parser/struct-literal-in-match-guard.rs +++ b/tests/ui/parser/struct-literal-in-match-guard.rs @@ -3,6 +3,8 @@ // Unlike `if` condition, `match` guards accept struct literals. // This is detected in . +#![feature(if_let_guard)] + #[derive(PartialEq)] struct Foo { x: isize, @@ -11,6 +13,7 @@ struct Foo { fn foo(f: Foo) { match () { () if f == Foo { x: 42 } => {} + () if let Foo { x: 0.. } = Foo { x: 42 } => {} _ => {} } } From caf2f33d745d42b0d301489d4c32992f72e7bff3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 14:31:14 +0000 Subject: [PATCH 05/14] Add type folder to SMIR --- compiler/rustc_smir/src/rustc_smir/mod.rs | 42 +++- compiler/rustc_smir/src/stable_mir/fold.rs | 207 ++++++++++++++++++ .../rustc_smir/src/stable_mir/mir/body.rs | 2 +- compiler/rustc_smir/src/stable_mir/mod.rs | 4 + compiler/rustc_smir/src/stable_mir/ty.rs | 6 + 5 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 compiler/rustc_smir/src/stable_mir/fold.rs diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 822a6e4865862..69a867b85de0c 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -97,8 +97,13 @@ impl<'tcx> Context for Tables<'tcx> { } fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind { - let ty = self.types[ty.0]; - ty.stable(self) + self.types[ty.0].clone().stable(self) + } + + fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty { + let n = self.types.len(); + self.types.push(MaybeStable::Stable(kind)); + stable_mir::ty::Ty(n) } fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { @@ -122,20 +127,47 @@ impl<'tcx> Context for Tables<'tcx> { } } +#[derive(Clone)] +pub enum MaybeStable { + Stable(S), + Rustc(R), +} + +impl<'tcx, S, R> MaybeStable { + fn stable(self, tables: &mut Tables<'tcx>) -> S + where + R: Stable<'tcx, T = S>, + { + match self { + MaybeStable::Stable(s) => s, + MaybeStable::Rustc(r) => r.stable(tables), + } + } +} + +impl PartialEq for MaybeStable { + fn eq(&self, other: &R) -> bool { + match self { + MaybeStable::Stable(_) => false, + MaybeStable::Rustc(r) => r == other, + } + } +} + pub struct Tables<'tcx> { pub tcx: TyCtxt<'tcx>, pub def_ids: Vec, pub alloc_ids: Vec, - pub types: Vec>, + pub types: Vec>>, } impl<'tcx> Tables<'tcx> { fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty { - if let Some(id) = self.types.iter().position(|&t| t == ty) { + if let Some(id) = self.types.iter().position(|t| *t == ty) { return stable_mir::ty::Ty(id); } let id = self.types.len(); - self.types.push(ty); + self.types.push(MaybeStable::Rustc(ty)); stable_mir::ty::Ty(id) } } diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/rustc_smir/src/stable_mir/fold.rs new file mode 100644 index 0000000000000..560a99cb4973f --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/fold.rs @@ -0,0 +1,207 @@ +use std::ops::ControlFlow; + +use crate::rustc_internal::Opaque; + +use super::ty::{ + Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, + Promoted, RigidTy, TermKind, Ty, UnevaluatedConst, +}; + +pub trait Folder: Sized { + type Break; + fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + ty.super_fold(self) + } + fn fold_const(&mut self, c: &Const) -> ControlFlow { + c.super_fold(self) + } +} + +pub trait Foldable: Sized + Clone { + fn fold(&self, folder: &mut V) -> ControlFlow { + self.super_fold(folder) + } + fn super_fold(&self, folder: &mut V) -> ControlFlow; +} + +impl Foldable for Ty { + fn fold(&self, folder: &mut V) -> ControlFlow { + folder.visit_ty(self) + } + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut kind = self.kind(); + match &mut kind { + super::ty::TyKind::RigidTy(ty) => *ty = ty.fold(folder)?, + super::ty::TyKind::Alias(_, alias) => alias.args = alias.args.fold(folder)?, + super::ty::TyKind::Param(_) => {} + super::ty::TyKind::Bound(_, _) => {} + } + ControlFlow::Continue(kind.into()) + } +} + +impl Foldable for Const { + fn fold(&self, folder: &mut V) -> ControlFlow { + folder.fold_const(self) + } + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut this = self.clone(); + match &mut this.literal { + super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?, + super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?, + super::ty::ConstantKind::ParamCt(param) => *param = param.fold(folder)?, + } + ControlFlow::Continue(this) + } +} + +impl Foldable for Opaque { + fn super_fold(&self, _folder: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + +impl Foldable for Allocation { + fn super_fold(&self, _folder: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + +impl Foldable for UnevaluatedConst { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let UnevaluatedConst { ty, def, args, promoted } = self; + ControlFlow::Continue(UnevaluatedConst { + ty: ty.fold(folder)?, + def: def.fold(folder)?, + args: args.fold(folder)?, + promoted: promoted.fold(folder)?, + }) + } +} + +impl Foldable for ConstDef { + fn super_fold(&self, _folder: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + +impl Foldable for Option { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + ControlFlow::Continue(match self { + Some(val) => Some(val.fold(folder)?), + None => None, + }) + } +} + +impl Foldable for Promoted { + fn super_fold(&self, _folder: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + +impl Foldable for GenericArgs { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + ControlFlow::Continue(GenericArgs(self.0.fold(folder)?)) + } +} + +impl Foldable for GenericArgKind { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut this = self.clone(); + match &mut this { + GenericArgKind::Lifetime(lt) => *lt = lt.fold(folder)?, + GenericArgKind::Type(t) => *t = t.fold(folder)?, + GenericArgKind::Const(c) => *c = c.fold(folder)?, + } + ControlFlow::Continue(this) + } +} + +impl Foldable for RigidTy { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut this = self.clone(); + match &mut this { + RigidTy::Bool + | RigidTy::Char + | RigidTy::Int(_) + | RigidTy::Uint(_) + | RigidTy::Float(_) + | RigidTy::Never + | RigidTy::Foreign(_) + | RigidTy::Str => {} + RigidTy::Array(t, c) => { + *t = t.fold(folder)?; + *c = c.fold(folder)?; + } + RigidTy::Slice(inner) => *inner = inner.fold(folder)?, + RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?, + RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?, + RigidTy::FnDef(_, args) => *args = args.fold(folder)?, + RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?, + RigidTy::Closure(_, args) => *args = args.fold(folder)?, + RigidTy::Generator(_, args, _) => *args = args.fold(folder)?, + RigidTy::Dynamic(pred, r, _) => { + *pred = pred.fold(folder)?; + *r = r.fold(folder)?; + } + RigidTy::Tuple(fields) => *fields = fields.fold(folder)?, + RigidTy::Adt(_, args) => *args = args.fold(folder)?, + } + ControlFlow::Continue(this) + } +} + +impl Foldable for Vec { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut this = self.clone(); + for arg in &mut this { + *arg = arg.fold(folder)?; + } + ControlFlow::Continue(this) + } +} + +impl Foldable for Binder { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + ControlFlow::Continue(Self { + value: self.value.fold(folder)?, + bound_vars: self.bound_vars.clone(), + }) + } +} + +impl Foldable for ExistentialPredicate { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + let mut this = self.clone(); + match &mut this { + ExistentialPredicate::Trait(tr) => tr.generic_args = tr.generic_args.fold(folder)?, + ExistentialPredicate::Projection(p) => { + p.term = p.term.fold(folder)?; + p.generic_args = p.generic_args.fold(folder)?; + } + ExistentialPredicate::AutoTrait(_) => {} + } + ControlFlow::Continue(this) + } +} + +impl Foldable for TermKind { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + ControlFlow::Continue(match self { + TermKind::Type(t) => TermKind::Type(t.fold(folder)?), + TermKind::Const(c) => TermKind::Const(c.fold(folder)?), + }) + } +} + +impl Foldable for FnSig { + fn super_fold(&self, folder: &mut V) -> ControlFlow { + ControlFlow::Continue(Self { + inputs_and_output: self.inputs_and_output.fold(folder)?, + c_variadic: self.c_variadic, + unsafety: self.unsafety, + abi: self.abi.clone(), + }) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 72f719c2a5e94..5957ae0ada9e7 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -391,7 +391,7 @@ pub enum Mutability { Mut, } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub enum Safety { Unsafe, Normal, diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index dad7c75c3406f..2bae9fd0709c6 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -18,6 +18,7 @@ use self::ty::{ }; use crate::rustc_smir::Tables; +pub mod fold; pub mod mir; pub mod ty; pub mod visitor; @@ -130,6 +131,9 @@ pub trait Context { /// Obtain the representation of a type. fn ty_kind(&mut self, ty: Ty) -> TyKind; + /// Create a new `Ty` from scratch without information from rustc. + fn mk_ty(&mut self, kind: TyKind) -> Ty; + /// HACK: Until we have fully stable consumers, we need an escape hatch /// to get `DefId`s out of `CrateItem`s. fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)); diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 1db6b1e3d28eb..5289e233a31dd 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -10,6 +10,12 @@ impl Ty { } } +impl From for Ty { + fn from(value: TyKind) -> Self { + with(|context| context.mk_ty(value)) + } +} + #[derive(Debug, Clone)] pub struct Const { pub literal: ConstantKind, From 7242c65f267de20cf16814f382189611504603ce Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 14:32:42 +0000 Subject: [PATCH 06/14] Fail to test argument instantiation since we don't have types for most constants --- tests/ui-fulldeps/stable-mir/crate-info.rs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 00dce3e004e63..cdb01192fd68f 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -108,6 +108,23 @@ fn test_stable_mir(tcx: TyCtxt<'_>) { stable_mir::mir::Terminator::Assert { .. } => {} other => panic!("{other:?}"), } + + let monomorphic = get_item(tcx, &items, (DefKind::Fn, "monomorphic")).unwrap(); + for block in monomorphic.body().blocks { + match &block.terminator { + stable_mir::mir::Terminator::Call { func, .. } => match func { + stable_mir::mir::Operand::Constant(c) => match &c.literal { + stable_mir::ty::ConstantKind::Allocated(alloc) => { + assert!(alloc.bytes.is_empty()) + } + other => panic!("{other:?}"), + }, + other => panic!("{other:?}"), + }, + stable_mir::mir::Terminator::Return => {} + other => panic!("{other:?}"), + } + } } // Use internal API to find a function in a crate. @@ -144,6 +161,16 @@ fn generate_input(path: &str) -> std::io::Result<()> { write!( file, r#" + fn generic(t: T) -> [(); U] {{ + _ = t; + [(); U] + }} + + pub fn monomorphic() {{ + generic::<(), 5>(()); + generic::(45); + }} + mod foo {{ pub fn bar(i: i32) -> i64 {{ i as i64 From a43ac063b9bce420b69eb95c51915b775763dffa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 14:37:30 +0000 Subject: [PATCH 07/14] Also use `Const` in `SMIR` instead of just `ConstantKind` --- compiler/rustc_smir/src/rustc_smir/mod.rs | 30 +++++++++++-------- .../rustc_smir/src/stable_mir/mir/body.rs | 4 +-- tests/ui-fulldeps/stable-mir/crate-info.rs | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 69a867b85de0c..00b6d5e237aa6 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1210,22 +1210,26 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { } impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { - type T = stable_mir::ty::ConstantKind; + type T = stable_mir::ty::Const; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { match *self { - ConstantKind::Ty(c) => c.stable(tables).literal, - ConstantKind::Unevaluated(unev_const, ty) => { - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - ty: tables.intern_ty(ty), - def: tables.const_def(unev_const.def), - args: unev_const.args.stable(tables), - promoted: unev_const.promoted.map(|u| u.as_u32()), - }) - } - ConstantKind::Val(val, ty) => { - stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables)) - } + ConstantKind::Ty(c) => c.stable(tables), + ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const { + literal: stable_mir::ty::ConstantKind::Unevaluated( + stable_mir::ty::UnevaluatedConst { + ty: tables.intern_ty(ty), + def: tables.const_def(unev_const.def), + args: unev_const.args.stable(tables), + promoted: unev_const.promoted.map(|u| u.as_u32()), + }, + ), + }, + ConstantKind::Val(val, ty) => stable_mir::ty::Const { + literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( + ty, val, tables, + )), + }, } } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 5957ae0ada9e7..449ca4b8145ed 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,6 +1,6 @@ use crate::rustc_internal::Opaque; use crate::stable_mir::ty::{ - AdtDef, ClosureDef, Const, ConstantKind, GeneratorDef, GenericArgs, Movability, Region, + AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, }; use crate::stable_mir::{self, ty::Ty, Span}; @@ -352,7 +352,7 @@ type UserTypeAnnotationIndex = usize; pub struct Constant { pub span: Span, pub user_ty: Option, - pub literal: ConstantKind, + pub literal: Const, } #[derive(Clone, Debug)] diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index cdb01192fd68f..a869b769176c1 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -113,7 +113,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) { for block in monomorphic.body().blocks { match &block.terminator { stable_mir::mir::Terminator::Call { func, .. } => match func { - stable_mir::mir::Operand::Constant(c) => match &c.literal { + stable_mir::mir::Operand::Constant(c) => match &c.literal.literal { stable_mir::ty::ConstantKind::Allocated(alloc) => { assert!(alloc.bytes.is_empty()) } From 5a129d1134c4f6818f929e6bb28a7c115043748c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 15:07:17 +0000 Subject: [PATCH 08/14] Add types to all constants --- compiler/rustc_smir/src/rustc_smir/mod.rs | 5 +++-- compiler/rustc_smir/src/stable_mir/fold.rs | 4 ++-- compiler/rustc_smir/src/stable_mir/ty.rs | 2 +- compiler/rustc_smir/src/stable_mir/visitor.rs | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 00b6d5e237aa6..a337c85ccc7b8 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1130,7 +1130,6 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { ty::PlaceholderCt(_) => unimplemented!(), ty::Unevaluated(uv) => { stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - ty: tables.intern_ty(self.ty()), def: tables.const_def(uv.def), args: uv.args.stable(tables), promoted: None, @@ -1138,6 +1137,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } ty::ExprCt(_) => unimplemented!(), }, + ty: tables.intern_ty(self.ty()), } } } @@ -1218,17 +1218,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const { literal: stable_mir::ty::ConstantKind::Unevaluated( stable_mir::ty::UnevaluatedConst { - ty: tables.intern_ty(ty), def: tables.const_def(unev_const.def), args: unev_const.args.stable(tables), promoted: unev_const.promoted.map(|u| u.as_u32()), }, ), + ty: tables.intern_ty(ty), }, ConstantKind::Val(val, ty) => stable_mir::ty::Const { literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( ty, val, tables, )), + ty: tables.intern_ty(ty), }, } } diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/rustc_smir/src/stable_mir/fold.rs index 560a99cb4973f..89f282d1afbf0 100644 --- a/compiler/rustc_smir/src/stable_mir/fold.rs +++ b/compiler/rustc_smir/src/stable_mir/fold.rs @@ -51,6 +51,7 @@ impl Foldable for Const { super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?, super::ty::ConstantKind::ParamCt(param) => *param = param.fold(folder)?, } + this.ty = this.ty.fold(folder)?; ControlFlow::Continue(this) } } @@ -69,9 +70,8 @@ impl Foldable for Allocation { impl Foldable for UnevaluatedConst { fn super_fold(&self, folder: &mut V) -> ControlFlow { - let UnevaluatedConst { ty, def, args, promoted } = self; + let UnevaluatedConst { def, args, promoted } = self; ControlFlow::Continue(UnevaluatedConst { - ty: ty.fold(folder)?, def: def.fold(folder)?, args: args.fold(folder)?, promoted: promoted.fold(folder)?, diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 5289e233a31dd..2361f6efe0d1f 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -19,6 +19,7 @@ impl From for Ty { #[derive(Debug, Clone)] pub struct Const { pub literal: ConstantKind, + pub ty: Ty, } type Ident = Opaque; @@ -298,7 +299,6 @@ pub enum ConstantKind { #[derive(Clone, Debug)] pub struct UnevaluatedConst { - pub ty: Ty, pub def: ConstDef, pub args: GenericArgs, pub promoted: Option, diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs index c928eb1381f79..6f0d96fae3757 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/rustc_smir/src/stable_mir/visitor.rs @@ -47,7 +47,8 @@ impl Visitable for Const { super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor), super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor), super::ty::ConstantKind::ParamCt(param) => param.visit(visitor), - } + }?; + self.ty.visit(visitor) } } @@ -65,8 +66,7 @@ impl Visitable for Allocation { impl Visitable for UnevaluatedConst { fn super_visit(&self, visitor: &mut V) -> ControlFlow { - let UnevaluatedConst { ty, def, args, promoted } = self; - ty.visit(visitor)?; + let UnevaluatedConst { def, args, promoted } = self; def.visit(visitor)?; args.visit(visitor)?; promoted.visit(visitor) From 8764b8778c7f85e0ef92d4e8e89da721bf80f5bf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 15:17:27 +0000 Subject: [PATCH 09/14] Deopaquify `ParamConst` --- compiler/rustc_smir/src/rustc_smir/mod.rs | 10 +++++++++- compiler/rustc_smir/src/stable_mir/fold.rs | 2 +- compiler/rustc_smir/src/stable_mir/ty.rs | 8 +++++++- compiler/rustc_smir/src/stable_mir/visitor.rs | 17 +++++++++-------- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index a337c85ccc7b8..5969f099a2e86 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1123,7 +1123,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { tables, )) } - ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)), + ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), ty::ErrorCt(_) => unreachable!(), ty::InferCt(_) => unreachable!(), ty::BoundCt(_, _) => unimplemented!(), @@ -1142,6 +1142,14 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::ParamConst { + type T = stable_mir::ty::ParamConst; + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::ParamConst; + ParamConst { index: self.index, name: self.name.to_string() } + } +} + impl<'tcx> Stable<'tcx> for ty::ParamTy { type T = stable_mir::ty::ParamTy; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/rustc_smir/src/stable_mir/fold.rs index 89f282d1afbf0..3567a5c5a3db6 100644 --- a/compiler/rustc_smir/src/stable_mir/fold.rs +++ b/compiler/rustc_smir/src/stable_mir/fold.rs @@ -49,7 +49,7 @@ impl Foldable for Const { match &mut this.literal { super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?, super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?, - super::ty::ConstantKind::ParamCt(param) => *param = param.fold(folder)?, + super::ty::ConstantKind::Param(_) => {} } this.ty = this.ty.fold(folder)?; ControlFlow::Continue(this) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 2361f6efe0d1f..7c58b640ec77f 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -294,7 +294,13 @@ pub struct Allocation { pub enum ConstantKind { Allocated(Allocation), Unevaluated(UnevaluatedConst), - ParamCt(Opaque), + Param(ParamConst), +} + +#[derive(Clone, Debug)] +pub struct ParamConst { + pub index: u32, + pub name: String, } #[derive(Clone, Debug)] diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs index 6f0d96fae3757..c86063d2ed6eb 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/rustc_smir/src/stable_mir/visitor.rs @@ -30,11 +30,12 @@ impl Visitable for Ty { } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self.kind() { - super::ty::TyKind::RigidTy(ty) => ty.visit(visitor), - super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor), - super::ty::TyKind::Param(_) => todo!(), - super::ty::TyKind::Bound(_, _) => todo!(), + super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?, + super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?, + super::ty::TyKind::Param(_) => {} + super::ty::TyKind::Bound(_, _) => {} } + ControlFlow::Continue(()) } } @@ -44,10 +45,10 @@ impl Visitable for Const { } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.literal { - super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor), - super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor), - super::ty::ConstantKind::ParamCt(param) => param.visit(visitor), - }?; + super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?, + super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?, + super::ty::ConstantKind::Param(_) => {} + } self.ty.visit(visitor) } } From a9de0c5c4d97bbd31a754067a0555bea44aa6510 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 15:18:42 +0000 Subject: [PATCH 10/14] Allow fetching the SMIR body of FnDefs --- compiler/rustc_smir/src/rustc_smir/mod.rs | 4 ++-- compiler/rustc_smir/src/stable_mir/mod.rs | 4 ++-- compiler/rustc_smir/src/stable_mir/ty.rs | 12 +++++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 5969f099a2e86..db09511c7fcb6 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -72,8 +72,8 @@ impl<'tcx> Context for Tables<'tcx> { impl_trait.stable(self) } - fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body { - let def_id = self[item.0]; + fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { + let def_id = self[item]; let mir = self.tcx.optimized_mir(def_id); stable_mir::mir::Body { blocks: mir diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 2bae9fd0709c6..391d989f52986 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -62,7 +62,7 @@ pub struct CrateItem(pub(crate) DefId); impl CrateItem { pub fn body(&self) -> mir::Body { - with(|cx| cx.mir_body(self)) + with(|cx| cx.mir_body(self.0)) } } @@ -113,7 +113,7 @@ pub trait Context { fn entry_fn(&mut self) -> Option; /// Retrieve all items of the local crate that have a MIR associated with them. fn all_local_items(&mut self) -> CrateItems; - fn mir_body(&mut self, item: &CrateItem) -> mir::Body; + fn mir_body(&mut self, item: DefId) -> mir::Body; fn all_trait_decls(&mut self) -> TraitDecls; fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; fn all_trait_impls(&mut self) -> ImplTraitDecls; diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 7c58b640ec77f..ad7a67275eeeb 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1,4 +1,8 @@ -use super::{mir::Mutability, mir::Safety, with, AllocId, DefId}; +use super::{ + mir::Safety, + mir::{Body, Mutability}, + with, AllocId, DefId, +}; use crate::rustc_internal::Opaque; #[derive(Copy, Clone, Debug)] @@ -95,6 +99,12 @@ pub struct ForeignDef(pub(crate) DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct FnDef(pub(crate) DefId); +impl FnDef { + pub fn body(&self) -> Body { + with(|ctx| ctx.mir_body(self.0)) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct ClosureDef(pub(crate) DefId); From c1e449cc4aaaea8cb7140de9737b95f891049cfa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 Sep 2023 15:18:53 +0000 Subject: [PATCH 11/14] Implement and test monomorphization --- compiler/rustc_smir/src/stable_mir/fold.rs | 27 +++++++++++++-- compiler/rustc_smir/src/stable_mir/ty.rs | 38 ++++++++++++++++++++++ tests/ui-fulldeps/stable-mir/crate-info.rs | 31 ++++++++++++++++-- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/rustc_smir/src/stable_mir/fold.rs index 3567a5c5a3db6..831cfb40a1542 100644 --- a/compiler/rustc_smir/src/stable_mir/fold.rs +++ b/compiler/rustc_smir/src/stable_mir/fold.rs @@ -3,8 +3,8 @@ use std::ops::ControlFlow; use crate::rustc_internal::Opaque; use super::ty::{ - Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - Promoted, RigidTy, TermKind, Ty, UnevaluatedConst, + Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind, + GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, }; pub trait Folder: Sized { @@ -205,3 +205,26 @@ impl Foldable for FnSig { }) } } + +pub enum Never {} + +/// In order to instantiate a `Foldable`'s generic parameters with specific arguments, +/// `GenericArgs` can be used as a `Folder` that replaces all mentions of generic params +/// with the entries in its list. +impl Folder for GenericArgs { + type Break = Never; + + fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + ControlFlow::Continue(match ty.kind() { + TyKind::Param(p) => self[p], + _ => *ty, + }) + } + + fn fold_const(&mut self, c: &Const) -> ControlFlow { + ControlFlow::Continue(match &c.literal { + ConstantKind::Param(p) => self[p.clone()].clone(), + _ => c.clone(), + }) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index ad7a67275eeeb..7e344dc516be9 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -138,6 +138,22 @@ pub struct ImplDef(pub(crate) DefId); #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); +impl std::ops::Index for GenericArgs { + type Output = Ty; + + fn index(&self, index: ParamTy) -> &Self::Output { + self.0[index.index as usize].expect_ty() + } +} + +impl std::ops::Index for GenericArgs { + type Output = Const; + + fn index(&self, index: ParamConst) -> &Self::Output { + self.0[index.index as usize].expect_const() + } +} + #[derive(Clone, Debug)] pub enum GenericArgKind { Lifetime(Region), @@ -145,6 +161,28 @@ pub enum GenericArgKind { Const(Const), } +impl GenericArgKind { + /// Panic if this generic argument is not a type, otherwise + /// return the type. + #[track_caller] + pub fn expect_ty(&self) -> &Ty { + match self { + GenericArgKind::Type(ty) => ty, + _ => panic!("{self:?}"), + } + } + + /// Panic if this generic argument is not a const, otherwise + /// return the const. + #[track_caller] + pub fn expect_const(&self) -> &Const { + match self { + GenericArgKind::Const(c) => c, + _ => panic!("{self:?}"), + } + } +} + #[derive(Clone, Debug)] pub enum TermKind { Type(Ty), diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index a869b769176c1..397f7b407b884 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -8,6 +8,7 @@ #![feature(rustc_private)] #![feature(assert_matches)] +#![feature(control_flow_enum)] extern crate rustc_hir; extern crate rustc_middle; @@ -15,7 +16,10 @@ extern crate rustc_smir; use rustc_hir::def::DefKind; use rustc_middle::ty::TyCtxt; -use rustc_smir::{rustc_internal, stable_mir}; +use rustc_smir::{ + rustc_internal, + stable_mir::{self, fold::Foldable}, +}; use std::assert_matches::assert_matches; use std::io::Write; @@ -115,7 +119,30 @@ fn test_stable_mir(tcx: TyCtxt<'_>) { stable_mir::mir::Terminator::Call { func, .. } => match func { stable_mir::mir::Operand::Constant(c) => match &c.literal.literal { stable_mir::ty::ConstantKind::Allocated(alloc) => { - assert!(alloc.bytes.is_empty()) + assert!(alloc.bytes.is_empty()); + match c.literal.ty.kind() { + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::FnDef( + def, + mut args, + )) => { + let func = def.body(); + match func.locals[1] + .fold(&mut args) + .continue_value() + .unwrap() + .kind() + { + stable_mir::ty::TyKind::RigidTy( + stable_mir::ty::RigidTy::Uint(_), + ) => {} + stable_mir::ty::TyKind::RigidTy( + stable_mir::ty::RigidTy::Tuple(_), + ) => {} + other => panic!("{other:?}"), + } + } + other => panic!("{other:?}"), + } } other => panic!("{other:?}"), }, From 98fa0c93ee031277e64eaee11fe9dbfe2147f532 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 5 Sep 2023 11:10:00 +0200 Subject: [PATCH 12/14] unconstrained region vars: do not ICE ICE baby --- .../src/traits/outlives_bounds.rs | 14 ++++------ .../implied-bounds-unconstrained-1.rs | 28 +++++++++++++++++++ .../implied-bounds-unconstrained-2.rs | 20 +++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 339baf611f3c3..32bbd626d4e49 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -57,16 +57,12 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { let ty = OpportunisticRegionResolver::new(self).fold_ty(ty); // We do not expect existential variables in implied bounds. - // We may however encounter unconstrained lifetime variables in invalid - // code. See #110161 for context. + // We may however encounter unconstrained lifetime variables + // in very rare cases. + // + // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for + // an example. assert!(!ty.has_non_region_infer()); - if ty.has_infer() { - self.tcx.sess.delay_span_bug( - self.tcx.def_span(body_id), - "skipped implied_outlives_bounds due to unconstrained lifetimes", - ); - return vec![]; - } let mut canonical_var_values = OriginalQueryValues::default(); let canonical_ty = diff --git a/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs b/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs new file mode 100644 index 0000000000000..025e5176ff7ee --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs @@ -0,0 +1,28 @@ +// check-pass + +// Regression test for #112832. +pub trait QueryDb { + type Db; +} + +pub struct QueryTable { + db: DB, + storage: Q, +} + +// We normalize `::Db` to `>::SendDb` +// using the where-bound. 'd is an unconstrained region variable which previously +// triggered an assert. +impl QueryTable::Db> where Q: for<'d> AsyncQueryFunction<'d> {} + +pub trait AsyncQueryFunction<'d>: QueryDb>::SendDb> { + type SendDb: 'd; +} + +pub trait QueryStorageOpsAsync +where + Q: for<'d> AsyncQueryFunction<'d>, +{ +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs b/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs new file mode 100644 index 0000000000000..976054facee5e --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs @@ -0,0 +1,20 @@ +// check-pass + +// Another minimized regression test for #112832. +trait Trait { + type Assoc; +} + +trait Sub<'a>: Trait>::SubAssoc> { + type SubAssoc; +} + +// By using the where-clause we normalize `::Assoc` to +// `>::SubAssoc` where `'a` is an unconstrained region +// variable. +fn foo(x: ::Assoc) +where + for<'a> T: Sub<'a>, +{} + +fn main() {} From 6a0b1bc177198037b60fc35b0e96afc7d60ad0e1 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 5 Sep 2023 17:52:39 +0300 Subject: [PATCH 13/14] make voldemort less cryptic --- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- tests/ui/drop-bounds/drop-bounds-impl-drop.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 56508a2a6ccd8..e812493b3dd39 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { }; let def_id = trait_predicate.trait_ref.def_id; if cx.tcx.lang_items().drop_trait() == Some(def_id) { - // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern. + // Explicitly allow `impl Drop`, a drop-guards-as-unnameable-type pattern. if trait_predicate.trait_ref.self_ty().is_impl_trait() { continue; } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0291cdd6c5799..fbbdfe5f14f92 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2857,7 +2857,7 @@ impl<'tcx> Ty<'tcx> { | ty::Uint(..) | ty::Float(..) => true, - // The voldemort ZSTs are fine. + // ZST which can't be named are fine. ty::FnDef(..) => true, ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(), diff --git a/tests/ui/drop-bounds/drop-bounds-impl-drop.rs b/tests/ui/drop-bounds/drop-bounds-impl-drop.rs index 063efc7b31abd..b4af333901efe 100644 --- a/tests/ui/drop-bounds/drop-bounds-impl-drop.rs +++ b/tests/ui/drop-bounds/drop-bounds-impl-drop.rs @@ -2,6 +2,7 @@ #![deny(drop_bounds)] // As a special exemption, `impl Drop` in the return position raises no error. // This allows a convenient way to return an unnamed drop guard. +// Voldemort here refers to types that are unnameable. fn voldemort_type() -> impl Drop { struct Voldemort; impl Drop for Voldemort { From 4684ffaf2ac5c7bb1467baf4e7f01469488c8ef2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 5 Sep 2023 17:20:31 +0200 Subject: [PATCH 14/14] if -> when --- library/core/src/intrinsics.rs | 4 ++-- library/core/src/ptr/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index f7469008d7c00..639e33762cf6b 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2706,12 +2706,12 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us /// Behavior is undefined if any of the following conditions are violated: /// /// * `src` must be [valid] for reads of `count * size_of::()` bytes, and must remain valid even -/// if `dst` is written for `count * size_of::()` bytes. (This means if the memory ranges +/// when `dst` is written for `count * size_of::()` bytes. (This means if the memory ranges /// overlap, the two pointers must not be subject to aliasing restrictions relative to each /// other.) /// /// * `dst` must be [valid] for writes of `count * size_of::()` bytes, and must remain valid even -/// if `src` is read for `count * size_of::()` bytes. +/// when `src` is read for `count * size_of::()` bytes. /// /// * Both `src` and `dst` must be properly aligned. /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 69d775075f369..452800516f713 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -795,7 +795,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * Both `x` and `y` must be [valid] for both reads and writes. They must remain valid even if the +/// * Both `x` and `y` must be [valid] for both reads and writes. They must remain valid even when the /// other pointer is written. (This means if the memory ranges overlap, the two pointers must not /// be subject to aliasing restrictions relative to each other.) ///