diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 18231af2bed9c..e8a8808428c27 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -381,17 +381,13 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { self.probe_ty_var(vid).ok() } - fn root_lt_var(&self, vid: ty::RegionVid) -> ty::RegionVid { - self.root_region_var(vid) - } - - fn probe_lt_var(&self, vid: ty::RegionVid) -> Option> { + fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Option> { let re = self .inner .borrow_mut() .unwrap_region_constraints() .opportunistic_resolve_var(self.tcx, vid); - if re.is_var() { None } else { Some(re) } + if *re == ty::ReVar(vid) { None } else { Some(re) } } fn root_ct_var(&self, vid: ConstVid) -> ConstVid { @@ -1367,10 +1363,6 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } - pub fn root_region_var(&self, var: ty::RegionVid) -> ty::RegionVid { - self.inner.borrow_mut().unwrap_region_constraints().root_var(var) - } - pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid { self.inner.borrow_mut().const_unification_table().find(var).vid } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 5c043b1d3dd64..cbd8040c9f10f 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -623,11 +623,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } - pub fn root_var(&mut self, vid: ty::RegionVid) -> ty::RegionVid { - let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut - ut.find(vid).vid - } - fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { match t { Glb => &mut self.glbs, diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index cb1f328577d02..ac2e8960b069b 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -242,16 +242,10 @@ impl, I: Interner> TypeFolder ty::ReVar(vid) => { assert_eq!( - self.infcx.root_lt_var(vid), - vid, - "region vid should have been resolved fully before canonicalization" - ); - assert_eq!( - self.infcx.probe_lt_var(vid), + self.infcx.opportunistic_resolve_lt_var(vid), None, "region vid should have been resolved fully before canonicalization" ); - match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 241a0c2231064..70313cc021e79 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -5,7 +5,9 @@ use rustc_middle::ty; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; -use rustc_middle::ty::{GenericPredicates, Instance, ParamEnv, ScalarInt, ValTree}; +use rustc_middle::ty::{ + GenericPredicates, Instance, ParamEnv, ScalarInt, TypeVisitableExt, ValTree, +}; use rustc_span::def_id::LOCAL_CRATE; use stable_mir::compiler_interface::Context; use stable_mir::mir::alloc::GlobalAlloc; @@ -324,7 +326,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); let instance = tables.instances[def]; - instance.ty(tables.tcx, ParamEnv::empty()).stable(&mut *tables) + assert!(!instance.has_non_region_param(), "{instance:?} needs further substitution"); + instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables) } fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 8c1767501d9a0..41ab4007a6759 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -36,6 +36,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { .collect(), self.arg_count, self.var_debug_info.iter().map(|info| info.stable(tables)).collect(), + self.spread_arg.stable(tables), ) } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 7d8339ab50366..7021bdda73501 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -57,7 +57,9 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { stable_mir::mir::CoroutineKind::Gen(source.stable(tables)) } CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine, - CoroutineKind::AsyncGen(_) => todo!(), + CoroutineKind::AsyncGen(source) => { + stable_mir::mir::CoroutineKind::AsyncGen(source.stable(tables)) + } } } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 8998001ec20ec..9c8e45b4338c6 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -32,11 +32,7 @@ impl InferCtxtLike for NoInfcx { None } - fn root_lt_var(&self, vid: I::InferRegion) -> I::InferRegion { - vid - } - - fn probe_lt_var(&self, _vid: I::InferRegion) -> Option { + fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option { None } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index 681f129a50b7c..28b71f0ea13f8 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -18,14 +18,14 @@ pub trait InferCtxtLike { lt: ::InferRegion, ) -> Option; - /// Resolve `InferRegion` to its root `InferRegion`. - fn root_lt_var( - &self, - vid: ::InferRegion, - ) -> ::InferRegion; - - /// Resolve `InferRegion` to its inferred region, if it has been equated with a non-infer region. - fn probe_lt_var( + /// Resolve `InferRegion` to its inferred region, if it has been equated with + /// a non-infer region. + /// + /// FIXME: This has slightly different semantics than `{probe,resolve}_{ty,ct}_var`, + /// that has to do with the fact unlike `Ty` or `Const` vars, in rustc, we may + /// not always be able to *name* the root region var from the universe of the + /// var we're trying to resolve. That's why it's called *opportunistic*. + fn opportunistic_resolve_lt_var( &self, vid: ::InferRegion, ) -> Option<::Region>; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 3dfe70963994c..5023af9ab79ec 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -22,6 +22,11 @@ pub struct Body { /// Debug information pertaining to user variables, including captures. pub var_debug_info: Vec, + + /// Mark an argument (which must be a tuple) as getting passed as its individual components. + /// + /// This is used for the "rust-call" ABI such as closures. + pub(super) spread_arg: Option, } pub type BasicBlockIdx = usize; @@ -36,6 +41,7 @@ impl Body { locals: LocalDecls, arg_count: usize, var_debug_info: Vec, + spread_arg: Option, ) -> Self { // If locals doesn't contain enough entries, it can lead to panics in // `ret_local`, `arg_locals`, and `inner_locals`. @@ -43,7 +49,7 @@ impl Body { locals.len() > arg_count, "A Body must contain at least a local for the return value and each of the function's arguments" ); - Self { blocks, locals, arg_count, var_debug_info } + Self { blocks, locals, arg_count, var_debug_info, spread_arg } } /// Return local that holds this function's return value. @@ -75,6 +81,11 @@ impl Body { self.locals.get(local) } + /// Get an iterator for all local declarations. + pub fn local_decls(&self) -> impl Iterator { + self.locals.iter().enumerate() + } + pub fn dump(&self, w: &mut W) -> io::Result<()> { writeln!(w, "{}", function_body(self))?; self.blocks @@ -98,6 +109,10 @@ impl Body { .collect::, _>>()?; Ok(()) } + + pub fn spread_arg(&self) -> Option { + self.spread_arg + } } type LocalDecls = Vec; @@ -248,6 +263,57 @@ pub enum AssertMessage { MisalignedPointerDereference { required: Operand, found: Operand }, } +impl AssertMessage { + pub fn description(&self) -> Result<&'static str, Error> { + match self { + AssertMessage::Overflow(BinOp::Add, _, _) => Ok("attempt to add with overflow"), + AssertMessage::Overflow(BinOp::Sub, _, _) => Ok("attempt to subtract with overflow"), + AssertMessage::Overflow(BinOp::Mul, _, _) => Ok("attempt to multiply with overflow"), + AssertMessage::Overflow(BinOp::Div, _, _) => Ok("attempt to divide with overflow"), + AssertMessage::Overflow(BinOp::Rem, _, _) => { + Ok("attempt to calculate the remainder with overflow") + } + AssertMessage::OverflowNeg(_) => Ok("attempt to negate with overflow"), + AssertMessage::Overflow(BinOp::Shr, _, _) => Ok("attempt to shift right with overflow"), + AssertMessage::Overflow(BinOp::Shl, _, _) => Ok("attempt to shift left with overflow"), + AssertMessage::Overflow(op, _, _) => Err(error!("`{:?}` cannot overflow", op)), + AssertMessage::DivisionByZero(_) => Ok("attempt to divide by zero"), + AssertMessage::RemainderByZero(_) => { + Ok("attempt to calculate the remainder with a divisor of zero") + } + AssertMessage::ResumedAfterReturn(CoroutineKind::Coroutine) => { + Ok("coroutine resumed after completion") + } + AssertMessage::ResumedAfterReturn(CoroutineKind::Async(_)) => { + Ok("`async fn` resumed after completion") + } + AssertMessage::ResumedAfterReturn(CoroutineKind::Gen(_)) => { + Ok("`async gen fn` resumed after completion") + } + AssertMessage::ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => { + Ok("`gen fn` should just keep returning `AssertMessage::None` after completion") + } + AssertMessage::ResumedAfterPanic(CoroutineKind::Coroutine) => { + Ok("coroutine resumed after panicking") + } + AssertMessage::ResumedAfterPanic(CoroutineKind::Async(_)) => { + Ok("`async fn` resumed after panicking") + } + AssertMessage::ResumedAfterPanic(CoroutineKind::Gen(_)) => { + Ok("`async gen fn` resumed after panicking") + } + AssertMessage::ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => { + Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking") + } + + AssertMessage::BoundsCheck { .. } => Ok("index out of bounds"), + AssertMessage::MisalignedPointerDereference { .. } => { + Ok("misaligned pointer dereference") + } + } + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum BinOp { Add, @@ -325,6 +391,7 @@ pub enum CoroutineKind { Async(CoroutineSource), Coroutine, Gen(CoroutineSource), + AsyncGen(CoroutineSource), } #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index bc5d4a3b8f477..c126de23c4b6f 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -1,6 +1,6 @@ use crate::crate_def::CrateDef; use crate::mir::Body; -use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, FnSig, GenericArgs, IndexedVal, Ty}; +use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol}; use std::fmt::{Debug, Formatter}; @@ -115,11 +115,6 @@ impl Instance { }) } - /// Get this function signature with all types already instantiated. - pub fn fn_sig(&self) -> FnSig { - self.ty().kind().fn_sig().unwrap().skip_binder() - } - /// Check whether this instance is an empty shim. /// /// Allow users to check if this shim can be ignored when called directly. diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 576087498abfa..8b7b488d312cf 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -260,6 +260,7 @@ pub fn pretty_assert_message(msg: &AssertMessage) -> String { ); pretty } + AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op), AssertMessage::OverflowNeg(op) => { let pretty_op = pretty_operand(op); pretty.push_str( @@ -279,17 +280,15 @@ pub fn pretty_assert_message(msg: &AssertMessage) -> String { ); pretty } - AssertMessage::ResumedAfterReturn(_) => { - format!("attempt to resume a generator after completion") - } - AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"), AssertMessage::MisalignedPointerDereference { required, found } => { let pretty_required = pretty_operand(required); let pretty_found = pretty_operand(found); pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str()); pretty } - _ => todo!(), + AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => { + msg.description().unwrap().to_string() + } } } diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index d46caad9a016b..98336a729009e 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -133,7 +133,7 @@ pub trait MirVisitor { } fn super_body(&mut self, body: &Body) { - let Body { blocks, locals: _, arg_count, var_debug_info } = body; + let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _ } = body; for bb in blocks { self.visit_basic_block(bb); diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index f473fd8dbb773..3d5e264104b3a 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -22,9 +22,7 @@ impl Debug for Ty { /// Constructors for `Ty`. impl Ty { /// Create a new type from a given kind. - /// - /// Note that not all types may be supported at this point. - fn from_rigid_kind(kind: RigidTy) -> Ty { + pub fn from_rigid_kind(kind: RigidTy) -> Ty { with(|cx| cx.new_rigid_ty(kind)) } @@ -77,6 +75,16 @@ impl Ty { pub fn bool_ty() -> Ty { Ty::from_rigid_kind(RigidTy::Bool) } + + /// Create a type representing a signed integer. + pub fn signed_ty(inner: IntTy) -> Ty { + Ty::from_rigid_kind(RigidTy::Int(inner)) + } + + /// Create a type representing an unsigned integer. + pub fn unsigned_ty(inner: UintTy) -> Ty { + Ty::from_rigid_kind(RigidTy::Uint(inner)) + } } impl Ty { diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index d311be5982d2d..ad66751133214 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -69,7 +69,7 @@ fn extract_elem_ty(ty: Ty) -> Ty { /// Check signature and type of `Vec::::new` and its generic version. fn test_vec_new(instance: mir::mono::Instance) { - let sig = instance.fn_sig(); + let sig = instance.ty().kind().fn_sig().unwrap().skip_binder(); assert_matches!(sig.inputs(), &[]); let elem_ty = extract_elem_ty(sig.output()); assert_matches!(elem_ty.kind(), TyKind::RigidTy(RigidTy::Uint(UintTy::U8))); diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs new file mode 100644 index 0000000000000..10fb7d525b7a1 --- /dev/null +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -0,0 +1,22 @@ +// compile-flags: -Znext-solver +// +// This is a gnarly test but I don't know how to minimize it, frankly. + +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete + +trait ToUnit<'a> { + type Unit; +} + +trait Overlap {} + +type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + +impl Overlap for T {} + +impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} +//~^ ERROR conflicting implementations of trait `Overlap` for type `fn(_)` +//~| ERROR cannot find type `Missing` in this scope + +fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr new file mode 100644 index 0000000000000..6b43b95fef3a6 --- /dev/null +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -0,0 +1,36 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/issue-118950-root-region.rs:18:55 + | +LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} + | ^^^^^^^ not found in this scope + +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-118950-root-region.rs:5:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) +error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` + --> $DIR/issue-118950-root-region.rs:18:1 + | +LL | impl Overlap for T {} + | ------------------------ first implementation here +LL | +LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` + +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0119, E0412. +For more information about an error, try `rustc --explain E0119`.