From c67aea7fddcf613abd3c76ee4ac31eced6da8265 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Mon, 24 Apr 2023 10:14:03 -0400 Subject: [PATCH 01/21] rustdoc: fix position of `default` in method rendering --- src/librustdoc/html/render/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f923f90545126..4ba648f8ad14c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -820,6 +820,7 @@ fn assoc_method( let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item"); let name = meth.name.as_ref().unwrap(); let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string(); + let defaultness = print_default_space(meth.is_default()); // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove // this condition. let constness = match render_mode { @@ -830,7 +831,6 @@ fn assoc_method( }; let asyncness = header.asyncness.print_with_space(); let unsafety = header.unsafety.print_with_space(); - let defaultness = print_default_space(meth.is_default()); let abi = print_abi_with_space(header.abi).to_string(); let href = assoc_href_attr(meth, link, cx); @@ -838,10 +838,10 @@ fn assoc_method( let generics_len = format!("{:#}", g.print(cx)).len(); let mut header_len = "fn ".len() + vis.len() + + defaultness.len() + constness.len() + asyncness.len() + unsafety.len() - + defaultness.len() + abi.len() + name.as_str().len() + generics_len; @@ -860,14 +860,14 @@ fn assoc_method( w.reserve(header_len + "{".len() + "".len()); write!( w, - "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \ + "{indent}{vis}{defaultness}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", indent = indent_str, vis = vis, + defaultness = defaultness, constness = constness, asyncness = asyncness, unsafety = unsafety, - defaultness = defaultness, abi = abi, href = href, name = name, From 13f58a8ea02fa6d62b0c44ceda9d5332562e1339 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Thu, 22 Jun 2023 22:28:29 -0400 Subject: [PATCH 02/21] Add tests for default unsafe trait methods --- tests/rustdoc/default-trait-method.rs | 43 +++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/tests/rustdoc/default-trait-method.rs b/tests/rustdoc/default-trait-method.rs index 6d0e339c48dc5..c895067816401 100644 --- a/tests/rustdoc/default-trait-method.rs +++ b/tests/rustdoc/default-trait-method.rs @@ -1,26 +1,45 @@ #![feature(min_specialization)] // @has default_trait_method/trait.Item.html -// @has - '//*[@id="tymethod.foo"]' 'fn foo()' -// @!has - '//*[@id="tymethod.foo"]' 'default fn foo()' -// @has - '//*[@id="tymethod.bar"]' 'fn bar()' -// @!has - '//*[@id="tymethod.bar"]' 'default fn bar()' -// @has - '//*[@id="method.baz"]' 'fn baz()' -// @!has - '//*[@id="method.baz"]' 'default fn baz()' pub trait Item { + // @has - '//*[@id="tymethod.foo"]' 'fn foo()' + // @!has - '//*[@id="tymethod.foo"]' 'default fn foo()' fn foo(); + + // @has - '//*[@id="tymethod.bar"]' 'fn bar()' + // @!has - '//*[@id="tymethod.bar"]' 'default fn bar()' fn bar(); - fn baz() {} + + // @has - '//*[@id="tymethod.baz"]' 'unsafe fn baz()' + // @!has - '//*[@id="tymethod.baz"]' 'default unsafe fn baz()' + unsafe fn baz(); + + // @has - '//*[@id="tymethod.quux"]' 'unsafe fn quux()' + // @!has - '//*[@id="tymethod.quux"]' 'default unsafe fn quux()' + unsafe fn quux(); + + // @has - '//*[@id="method.xyzzy"]' 'fn xyzzy()' + // @!has - '//*[@id="method.xyzzy"]' 'default fn xyzzy()' + fn xyzzy() {} } // @has default_trait_method/struct.Foo.html -// @has - '//*[@id="method.foo"]' 'default fn foo()' -// @has - '//*[@id="method.bar"]' 'fn bar()' -// @!has - '//*[@id="method.bar"]' 'default fn bar()' -// @has - '//*[@id="method.baz"]' 'fn baz()' -// @!has - '//*[@id="method.baz"]' 'default fn baz()' pub struct Foo; impl Item for Foo { + // @has - '//*[@id="method.foo"]' 'default fn foo()' default fn foo() {} + + // @has - '//*[@id="method.bar"]' 'fn bar()' + // @!has - '//*[@id="method.bar"]' 'default fn bar()' fn bar() {} + + // @has - '//*[@id="method.baz"]' 'default unsafe fn baz()' + default unsafe fn baz() {} + + // @has - '//*[@id="method.quux"]' 'unsafe fn quux()' + // @!has - '//*[@id="method.quux"]' 'default unsafe fn quux()' + unsafe fn quux() {} + + // @has - '//*[@id="method.xyzzy"]' 'fn xyzzy()' + // @!has - '//*[@id="method.xyzzy"]' 'default fn xyzzy()' } From 9e5a67e57f715ec5eda915db1261cdf4c4a04642 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 10 Jul 2023 09:33:34 +0000 Subject: [PATCH 03/21] Permit pre-evaluated constants in simd_shuffle --- .../rustc_codegen_ssa/src/mir/constant.rs | 14 ++++++++++++++ tests/ui/simd/shuffle.rs | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 1c5031dfc4b4b..47a166e4e1be4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -67,6 +67,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Result>, ErrorHandled> { let uv = match constant.literal { mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(), + mir::ConstantKind::Ty(c) => match c.kind() { + // A constant that came from a const generic but was then used as an argument to old-style + // simd_shuffle (passing as argument instead of as a generic param). + rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)), + other => span_bug!(constant.span, "{other:#?}"), + }, + // We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate + // a constant and write that value back into `Operand`s. This could happen, but is unlikely. + // Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care + // around intrinsics. For an issue to happen here, it would require a macro expanding to a + // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but + // the user pass through arbitrary expressions. + // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real + // const generic. other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 3592adfdc6ad1..de41c9e25ddd5 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -1,14 +1,21 @@ //run-pass #![feature(repr_simd, platform_intrinsics)] +#![allow(incomplete_features)] +#![feature(adt_const_params)] extern "platform-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; + fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; } #[derive(Copy, Clone)] #[repr(simd)] struct Simd([T; N]); +pub unsafe fn __shuffle_vector16(x: T, y: T) -> U { + simd_shuffle16(x, y, IDX) +} + fn main() { const I1: [u32; 4] = [0, 2, 4, 6]; const I2: [u32; 2] = [1, 5]; @@ -21,4 +28,16 @@ fn main() { let y: Simd = simd_shuffle(a, b, I2); assert_eq!(y.0, [1, 5]); } + // Test that an indirection (via an unnamed constant) + // through a const generic parameter also works. + // See https://github.com/rust-lang/rust/issues/113500 for details. + let a = Simd::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let b = Simd::([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); + unsafe { + __shuffle_vector16::< + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] }, + Simd, + Simd, + >(a, b); + } } From 9b32319205dd207c9bdb501ee353a542fc10674d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 11:18:40 -0300 Subject: [PATCH 04/21] Add Foreign to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 ++++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 4 +++- compiler/rustc_smir/src/stable_mir/ty.rs | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 527d5220564cc..2ac3046ce6d76 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -31,6 +31,10 @@ pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef { with_tables(|t| t.adt_def(did)) } +pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef { + with_tables(|t| t.foreign_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -44,6 +48,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::AdtDef(self.create_def_id(did)) } + pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef { + stable_mir::ty::ForeignDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 0e5de1e74d32d..13bda35d69278 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -113,7 +113,9 @@ impl<'tcx> Tables<'tcx> { .collect(), ), )), - ty::Foreign(_) => todo!(), + ty::Foreign(def_id) => { + TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id))) + } ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant))) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 7ae07efb729dd..162dfe05becd5 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -26,6 +26,7 @@ pub enum RigidTy { Uint(UintTy), Float(FloatTy), Adt(AdtDef, AdtSubsts), + Foreign(ForeignDef), Str, Array(Ty, Const), Slice(Ty), @@ -60,6 +61,9 @@ pub enum FloatTy { F64, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ForeignDef(pub(crate) DefId); + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AdtDef(pub(crate) DefId); From caa01adbd061b17e97ada679e87a96da713310fa Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 12:02:35 -0300 Subject: [PATCH 05/21] Add Never to SMIR --- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/rustc_smir/src/stable_mir/ty.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 13bda35d69278..922bbf029387d 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -132,7 +132,7 @@ impl<'tcx> Tables<'tcx> { ty::Dynamic(_, _, _) => todo!(), ty::Closure(_, _) => todo!(), ty::Generator(_, _, _) => todo!(), - ty::Never => todo!(), + ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( fields.iter().map(|ty| self.intern_ty(ty)).collect(), )), diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 162dfe05becd5..571fd0d747244 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -32,6 +32,7 @@ pub enum RigidTy { Slice(Ty), RawPtr(Ty, Mutability), Ref(Region, Ty, Mutability), + Never, Tuple(Vec), } From 68077d58272901590fb2b1de5dc551a88a1dc36c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 12:11:49 -0300 Subject: [PATCH 06/21] Rename SMIR AdtSubsts to GenericArgs --- compiler/rustc_smir/src/rustc_smir/mod.rs | 8 ++++---- compiler/rustc_smir/src/stable_mir/ty.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 922bbf029387d..f624c4dc8ff45 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -8,7 +8,7 @@ //! For now, we are developing everything inside `rustc`, thus, we keep this module private. use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::ty::{AdtSubsts, FloatTy, GenericArgKind, IntTy, RigidTy, TyKind, UintTy}; +use crate::stable_mir::ty::{FloatTy, GenericArgs, GenericArgKind, IntTy, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -94,10 +94,10 @@ impl<'tcx> Tables<'tcx> { ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)), ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)), }, - ty::Adt(adt_def, substs) => TyKind::RigidTy(RigidTy::Adt( + ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( rustc_internal::adt_def(adt_def.did()), - AdtSubsts( - substs + GenericArgs( + generic_args .iter() .map(|arg| match arg.unpack() { ty::GenericArgKind::Lifetime(region) => { diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 571fd0d747244..36b562850e953 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -25,7 +25,7 @@ pub enum RigidTy { Int(IntTy), Uint(UintTy), Float(FloatTy), - Adt(AdtDef, AdtSubsts), + Adt(AdtDef, GenericArgs), Foreign(ForeignDef), Str, Array(Ty, Const), @@ -69,7 +69,7 @@ pub struct ForeignDef(pub(crate) DefId); pub struct AdtDef(pub(crate) DefId); #[derive(Clone, Debug)] -pub struct AdtSubsts(pub Vec); +pub struct GenericArgs(pub Vec); #[derive(Clone, Debug)] pub enum GenericArgKind { From e5c0b96e2408850d6db27a8d69339fa6a6c78455 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 12:16:38 -0300 Subject: [PATCH 07/21] Add FnDef ty to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 +++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 22 +++++++++++++++++-- compiler/rustc_smir/src/stable_mir/ty.rs | 4 ++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 2ac3046ce6d76..e4f129bc1d6ce 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -35,6 +35,10 @@ pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef { with_tables(|t| t.foreign_def(did)) } +pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef { + with_tables(|t| t.fn_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -52,6 +56,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::ForeignDef(self.create_def_id(did)) } + pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef { + stable_mir::ty::FnDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index f624c4dc8ff45..81ca0f985cc7c 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -8,7 +8,7 @@ //! For now, we are developing everything inside `rustc`, thus, we keep this module private. use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::ty::{FloatTy, GenericArgs, GenericArgKind, IntTy, RigidTy, TyKind, UintTy}; +use crate::stable_mir::ty::{FloatTy, GenericArgKind, GenericArgs, IntTy, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -127,7 +127,25 @@ impl<'tcx> Tables<'tcx> { ty::Ref(region, ty, mutbl) => { TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable())) } - ty::FnDef(_, _) => todo!(), + ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( + rustc_internal::fn_def(*def_id), + GenericArgs( + generic_args + .iter() + .map(|arg| match arg.unpack() { + ty::GenericArgKind::Lifetime(region) => { + GenericArgKind::Lifetime(opaque(®ion)) + } + ty::GenericArgKind::Type(ty) => { + GenericArgKind::Type(self.intern_ty(ty)) + } + ty::GenericArgKind::Const(const_) => { + GenericArgKind::Const(opaque(&const_)) + } + }) + .collect(), + ), + )), ty::FnPtr(_) => todo!(), ty::Dynamic(_, _, _) => todo!(), ty::Closure(_, _) => todo!(), diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 36b562850e953..f3dbde907a03a 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -32,6 +32,7 @@ pub enum RigidTy { Slice(Ty), RawPtr(Ty, Mutability), Ref(Region, Ty, Mutability), + FnDef(FnDef, GenericArgs), Never, Tuple(Vec), } @@ -65,6 +66,9 @@ pub enum FloatTy { #[derive(Clone, PartialEq, Eq, Debug)] pub struct ForeignDef(pub(crate) DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FnDef(pub(crate) DefId); + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AdtDef(pub(crate) DefId); From c5c38cdee80e42c374a0afddeb843851abfd105b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 12:19:41 -0300 Subject: [PATCH 08/21] Add Closure ty to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 ++++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 20 ++++++++++++++++++- compiler/rustc_smir/src/stable_mir/ty.rs | 4 ++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index e4f129bc1d6ce..d32215186a63d 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -39,6 +39,10 @@ pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef { with_tables(|t| t.fn_def(did)) } +pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef { + with_tables(|t| t.closure_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -60,6 +64,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::FnDef(self.create_def_id(did)) } + pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef { + stable_mir::ty::ClosureDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 81ca0f985cc7c..b542cc84f6a72 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -148,7 +148,25 @@ impl<'tcx> Tables<'tcx> { )), ty::FnPtr(_) => todo!(), ty::Dynamic(_, _, _) => todo!(), - ty::Closure(_, _) => todo!(), + ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( + rustc_internal::closure_def(*def_id), + GenericArgs( + generic_args + .iter() + .map(|arg| match arg.unpack() { + ty::GenericArgKind::Lifetime(region) => { + GenericArgKind::Lifetime(opaque(®ion)) + } + ty::GenericArgKind::Type(ty) => { + GenericArgKind::Type(self.intern_ty(ty)) + } + ty::GenericArgKind::Const(const_) => { + GenericArgKind::Const(opaque(&const_)) + } + }) + .collect(), + ), + )), ty::Generator(_, _, _) => todo!(), ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index f3dbde907a03a..758e0bb7de70d 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -33,6 +33,7 @@ pub enum RigidTy { RawPtr(Ty, Mutability), Ref(Region, Ty, Mutability), FnDef(FnDef, GenericArgs), + Closure(ClosureDef, GenericArgs), Never, Tuple(Vec), } @@ -69,6 +70,9 @@ pub struct ForeignDef(pub(crate) DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct FnDef(pub(crate) DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ClosureDef(pub(crate) DefId); + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AdtDef(pub(crate) DefId); From ed323476891eb948d6c6e6390756f0052c765453 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jul 2023 13:38:16 -0300 Subject: [PATCH 09/21] Add Generator to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 ++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 28 +++++++++++++++++-- compiler/rustc_smir/src/stable_mir/ty.rs | 10 +++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index d32215186a63d..ccb12c27107e4 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -43,6 +43,10 @@ pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef { with_tables(|t| t.closure_def(did)) } +pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef { + with_tables(|t| t.generator_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -68,6 +72,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::ClosureDef(self.create_def_id(did)) } + pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef { + stable_mir::ty::GeneratorDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index b542cc84f6a72..8bc7ef325cfff 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -8,8 +8,9 @@ //! For now, we are developing everything inside `rustc`, thus, we keep this module private. use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::ty::{FloatTy, GenericArgKind, GenericArgs, IntTy, RigidTy, TyKind, UintTy}; +use crate::stable_mir::ty::{FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; +use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -167,7 +168,30 @@ impl<'tcx> Tables<'tcx> { .collect(), ), )), - ty::Generator(_, _, _) => todo!(), + ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( + rustc_internal::generator_def(*def_id), + GenericArgs( + generic_args + .iter() + .map(|arg| match arg.unpack() { + ty::GenericArgKind::Lifetime(region) => { + GenericArgKind::Lifetime(opaque(®ion)) + } + ty::GenericArgKind::Type(ty) => { + GenericArgKind::Type(self.intern_ty(ty)) + } + ty::GenericArgKind::Const(const_) => { + GenericArgKind::Const(opaque(&const_)) + } + }) + .collect(), + ), + match movability { + hir::Movability::Static => Movability::Static, + hir::Movability::Movable => Movability::Movable, + + } + )), ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( fields.iter().map(|ty| self.intern_ty(ty)).collect(), diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 758e0bb7de70d..1ccb30343ed84 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -34,6 +34,7 @@ pub enum RigidTy { Ref(Region, Ty, Mutability), FnDef(FnDef, GenericArgs), Closure(ClosureDef, GenericArgs), + Generator(GeneratorDef, GenericArgs, Movability), Never, Tuple(Vec), } @@ -64,6 +65,12 @@ pub enum FloatTy { F64, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Movability { + Static, + Movable, +} + #[derive(Clone, PartialEq, Eq, Debug)] pub struct ForeignDef(pub(crate) DefId); @@ -73,6 +80,9 @@ pub struct FnDef(pub(crate) DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct ClosureDef(pub(crate) DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct GeneratorDef(pub(crate) DefId); + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AdtDef(pub(crate) DefId); From db35f1de2f7e4a23e6401ee7e2a3335c29d33519 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 19 Jul 2023 11:01:58 -0300 Subject: [PATCH 10/21] Extract generic_args function --- compiler/rustc_smir/src/rustc_smir/mod.rs | 93 +++++++---------------- 1 file changed, 26 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 8bc7ef325cfff..f512a98f41a4d 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -8,7 +8,9 @@ //! For now, we are developing everything inside `rustc`, thus, we keep this module private. use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::ty::{FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy}; +use crate::stable_mir::ty::{ + FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy, +}; use crate::stable_mir::{self, Context}; use rustc_hir as hir; use rustc_middle::mir; @@ -97,22 +99,7 @@ impl<'tcx> Tables<'tcx> { }, ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( rustc_internal::adt_def(adt_def.did()), - GenericArgs( - generic_args - .iter() - .map(|arg| match arg.unpack() { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(opaque(®ion)) - } - ty::GenericArgKind::Type(ty) => { - GenericArgKind::Type(self.intern_ty(ty)) - } - ty::GenericArgKind::Const(const_) => { - GenericArgKind::Const(opaque(&const_)) - } - }) - .collect(), - ), + self.generic_args(generic_args), )), ty::Foreign(def_id) => { TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id))) @@ -130,67 +117,21 @@ impl<'tcx> Tables<'tcx> { } ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( rustc_internal::fn_def(*def_id), - GenericArgs( - generic_args - .iter() - .map(|arg| match arg.unpack() { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(opaque(®ion)) - } - ty::GenericArgKind::Type(ty) => { - GenericArgKind::Type(self.intern_ty(ty)) - } - ty::GenericArgKind::Const(const_) => { - GenericArgKind::Const(opaque(&const_)) - } - }) - .collect(), - ), + self.generic_args(generic_args), )), ty::FnPtr(_) => todo!(), ty::Dynamic(_, _, _) => todo!(), ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( rustc_internal::closure_def(*def_id), - GenericArgs( - generic_args - .iter() - .map(|arg| match arg.unpack() { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(opaque(®ion)) - } - ty::GenericArgKind::Type(ty) => { - GenericArgKind::Type(self.intern_ty(ty)) - } - ty::GenericArgKind::Const(const_) => { - GenericArgKind::Const(opaque(&const_)) - } - }) - .collect(), - ), + self.generic_args(generic_args), )), ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( rustc_internal::generator_def(*def_id), - GenericArgs( - generic_args - .iter() - .map(|arg| match arg.unpack() { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(opaque(®ion)) - } - ty::GenericArgKind::Type(ty) => { - GenericArgKind::Type(self.intern_ty(ty)) - } - ty::GenericArgKind::Const(const_) => { - GenericArgKind::Const(opaque(&const_)) - } - }) - .collect(), - ), + self.generic_args(generic_args), match movability { hir::Movability::Static => Movability::Static, hir::Movability::Movable => Movability::Movable, - - } + }, )), ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( @@ -217,6 +158,24 @@ impl<'tcx> Tables<'tcx> { self.types.push(ty); stable_mir::ty::Ty(id) } + + fn generic_args( + &mut self, + generic_args: &ty::GenericArgs<'tcx>, + ) -> stable_mir::ty::GenericArgs { + GenericArgs( + generic_args + .iter() + .map(|arg| match arg.unpack() { + ty::GenericArgKind::Lifetime(region) => { + GenericArgKind::Lifetime(opaque(®ion)) + } + ty::GenericArgKind::Type(ty) => GenericArgKind::Type(self.intern_ty(ty)), + ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)), + }) + .collect(), + ) + } } /// Build a stable mir crate from a given crate number. From c5819b2b9b51a6be498c11ceadae00ffbed8946d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 19 Jul 2023 11:03:39 -0300 Subject: [PATCH 11/21] Remove FIXMEs a lot of things need fixes --- compiler/rustc_smir/src/stable_mir/ty.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 1ccb30343ed84..ba120be04b2f5 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -91,9 +91,7 @@ pub struct GenericArgs(pub Vec); #[derive(Clone, Debug)] pub enum GenericArgKind { - // FIXME add proper region Lifetime(Region), Type(Ty), - // FIXME add proper const Const(Const), } From 2009b4a5cc1d097188da4396f423a076ac6282a1 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Thu, 20 Jul 2023 17:46:32 +0900 Subject: [PATCH 12/21] Remove adjustments that used to be necessary for search's crate selector appearance (padding) to look identical on Firefox. New versions of Firefox appear to have changed behavior to agree with Chrome. --- src/librustdoc/html/static/css/rustdoc.css | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 94e778406f8b6..b1de8c1529e78 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -776,7 +776,6 @@ table, } #crate-search { min-width: 115px; - /* keep these two in sync with "@-moz-document url-prefix()" below */ padding: 0 23px 0 4px; /* prevents the s */ -@-moz-document url-prefix() { - #crate-search { - padding-left: 0px; /* == 4px - 4px */ - padding-right: 19px; /* == 23px - 4px */ - } -} /* pseudo-element for holding the dropdown-arrow image; needs to be a separate thing so that we can apply CSS-filters to change the arrow color in themes */ #crate-search-div::after { From c7428d50520446ccd44ca89bbbf4ff7a4725570e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 20 Jul 2023 08:53:09 +0000 Subject: [PATCH 13/21] Monomorphize constants before inspecting them --- compiler/rustc_codegen_ssa/src/mir/constant.rs | 2 +- tests/ui/simd/shuffle.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 47a166e4e1be4..babcf9bee2491 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &self, constant: &mir::Constant<'tcx>, ) -> Result>, ErrorHandled> { - let uv = match constant.literal { + let uv = match self.monomorphize(constant.literal) { mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(), mir::ConstantKind::Ty(c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to old-style diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index de41c9e25ddd5..461243d489283 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -1,4 +1,7 @@ -//run-pass +// run-pass +// revisions: opt noopt +//[noopt] compile-flags: -Copt-level=0 +//[opt] compile-flags: -O #![feature(repr_simd, platform_intrinsics)] #![allow(incomplete_features)] #![feature(adt_const_params)] From fdaec57a28ab6a8cd60fd7a2842d366a9b452a2e Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Jul 2023 17:03:22 +0200 Subject: [PATCH 14/21] XSimplifiedType to SimplifiedType::X --- .../src/coherence/orphan.rs | 10 +- compiler/rustc_middle/src/ty/fast_reject.rs | 112 +++++++++--------- .../src/solve/trait_goals.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/types.rs | 51 ++++---- .../src/utils/internal_lints/invalid_paths.rs | 8 +- src/tools/clippy/clippy_utils/src/lib.rs | 47 ++++---- 7 files changed, 116 insertions(+), 118 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 05c78f5708814..21ffbefcd0810 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -568,10 +568,10 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: impl<'tcx> TypeVisitor> for DisableAutoTraitVisitor<'tcx> { type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { let tcx = self.tcx; - if t != self.self_ty_root { - for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) { + if ty != self.self_ty_root { + for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, ty) { match tcx.impl_polarity(impl_def_id) { ImplPolarity::Negative => return ControlFlow::Break(()), ImplPolarity::Reservation => {} @@ -584,7 +584,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: } } - match t.kind() { + match ty.kind() { ty::Adt(def, args) if def.is_phantom_data() => args.visit_with(self), ty::Adt(def, args) => { // @lcnr: This is the only place where cycles can happen. We avoid this @@ -599,7 +599,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: ControlFlow::Continue(()) } - _ => t.super_visit_with(self), + _ => ty.super_visit_with(self), } } } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index e86ff4d26aaab..deb4dcf1f760a 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -6,35 +6,33 @@ use std::fmt::Debug; use std::hash::Hash; use std::iter; -use self::SimplifiedType::*; - /// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] pub enum SimplifiedType { - BoolSimplifiedType, - CharSimplifiedType, - IntSimplifiedType(ty::IntTy), - UintSimplifiedType(ty::UintTy), - FloatSimplifiedType(ty::FloatTy), - AdtSimplifiedType(DefId), - ForeignSimplifiedType(DefId), - StrSimplifiedType, - ArraySimplifiedType, - SliceSimplifiedType, - RefSimplifiedType(Mutability), - PtrSimplifiedType(Mutability), - NeverSimplifiedType, - TupleSimplifiedType(usize), + Bool, + Char, + Int(ty::IntTy), + Uint(ty::UintTy), + Float(ty::FloatTy), + Adt(DefId), + Foreign(DefId), + Str, + Array, + Slice, + Ref(Mutability), + Ptr(Mutability), + Never, + Tuple(usize), /// A trait object, all of whose components are markers /// (e.g., `dyn Send + Sync`). - MarkerTraitObjectSimplifiedType, - TraitSimplifiedType(DefId), - ClosureSimplifiedType(DefId), - GeneratorSimplifiedType(DefId), - GeneratorWitnessSimplifiedType(usize), - GeneratorWitnessMIRSimplifiedType(DefId), - FunctionSimplifiedType(usize), - PlaceholderSimplifiedType, + MarkerTraitObject, + Trait(DefId), + Closure(DefId), + Generator(DefId), + GeneratorWitness(usize), + GeneratorWitnessMIR(DefId), + Function(usize), + Placeholder, } /// Generic parameters are pretty much just bound variables, e.g. @@ -110,34 +108,36 @@ pub fn simplify_type<'tcx>( treat_params: TreatParams, ) -> Option { match *ty.kind() { - ty::Bool => Some(BoolSimplifiedType), - ty::Char => Some(CharSimplifiedType), - ty::Int(int_type) => Some(IntSimplifiedType(int_type)), - ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)), - ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), - ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())), - ty::Str => Some(StrSimplifiedType), - ty::Array(..) => Some(ArraySimplifiedType), - ty::Slice(..) => Some(SliceSimplifiedType), - ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), + ty::Bool => Some(SimplifiedType::Bool), + ty::Char => Some(SimplifiedType::Char), + ty::Int(int_type) => Some(SimplifiedType::Int(int_type)), + ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)), + ty::Float(float_type) => Some(SimplifiedType::Float(float_type)), + ty::Adt(def, _) => Some(SimplifiedType::Adt(def.did())), + ty::Str => Some(SimplifiedType::Str), + ty::Array(..) => Some(SimplifiedType::Array), + ty::Slice(..) => Some(SimplifiedType::Slice), + ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { - Some(TraitSimplifiedType(principal_def_id)) + Some(SimplifiedType::Trait(principal_def_id)) } - _ => Some(MarkerTraitObjectSimplifiedType), + _ => Some(SimplifiedType::MarkerTraitObject), }, - ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)), - ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), - ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), - ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())), - ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)), - ty::Never => Some(NeverSimplifiedType), - ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())), - ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), - ty::Placeholder(..) => Some(PlaceholderSimplifiedType), + ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), + ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), + ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)), + ty::GeneratorWitness(tys) => { + Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len())) + } + ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)), + ty::Never => Some(SimplifiedType::Never), + ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), + ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), + ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { TreatParams::ForLookup | TreatParams::NextSolverLookup => { - Some(PlaceholderSimplifiedType) + Some(SimplifiedType::Placeholder) } TreatParams::AsCandidateKey => None, }, @@ -147,11 +147,13 @@ pub fn simplify_type<'tcx>( // // We will have to be careful with lazy normalization here. // FIXME(lazy_normalization): This is probably not right... - TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType), - TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatParams::ForLookup if !ty.has_non_region_infer() => { + Some(SimplifiedType::Placeholder) + } + TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder), TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, - ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), + ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, } } @@ -159,12 +161,12 @@ pub fn simplify_type<'tcx>( impl SimplifiedType { pub fn def(self) -> Option { match self { - AdtSimplifiedType(d) - | ForeignSimplifiedType(d) - | TraitSimplifiedType(d) - | ClosureSimplifiedType(d) - | GeneratorSimplifiedType(d) - | GeneratorWitnessMIRSimplifiedType(d) => Some(d), + SimplifiedType::Adt(d) + | SimplifiedType::Foreign(d) + | SimplifiedType::Trait(d) + | SimplifiedType::Closure(d) + | SimplifiedType::Generator(d) + | SimplifiedType::GeneratorWitnessMIR(d) => Some(d), _ => None, } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index e7867eead1597..29889614620dd 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -686,7 +686,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Tuple(_) | ty::Adt(_, _) // FIXME: Handling opaques here is kinda sus. Especially because we - // simplify them to PlaceholderSimplifiedType. + // simplify them to SimplifiedType::Placeholder. | ty::Alias(ty::Opaque, _) => { let mut disqualifying_impl = None; self.tcx().for_each_relevant_impl_treating_projections( diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5e2e2d2495000..cfd9875e1c8fa 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -12,6 +12,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; @@ -314,9 +315,8 @@ pub(crate) fn build_impls( // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { - use rustc_middle::ty::fast_reject::SimplifiedType::*; let type_ = - if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) }; + if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; for &did in tcx.incoherent_impls(type_) { build_impl(cx, did, attrs, ret); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index cfe62407fd35d..ddef165a05479 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1776,7 +1776,6 @@ impl PrimitiveType { } pub(crate) fn simplified_types() -> &'static SimplifiedTypes { - use ty::fast_reject::SimplifiedType::*; use ty::{FloatTy, IntTy, UintTy}; use PrimitiveType::*; static CELL: OnceCell = OnceCell::new(); @@ -1784,38 +1783,38 @@ impl PrimitiveType { let single = |x| iter::once(x).collect(); CELL.get_or_init(move || { map! { - Isize => single(IntSimplifiedType(IntTy::Isize)), - I8 => single(IntSimplifiedType(IntTy::I8)), - I16 => single(IntSimplifiedType(IntTy::I16)), - I32 => single(IntSimplifiedType(IntTy::I32)), - I64 => single(IntSimplifiedType(IntTy::I64)), - I128 => single(IntSimplifiedType(IntTy::I128)), - Usize => single(UintSimplifiedType(UintTy::Usize)), - U8 => single(UintSimplifiedType(UintTy::U8)), - U16 => single(UintSimplifiedType(UintTy::U16)), - U32 => single(UintSimplifiedType(UintTy::U32)), - U64 => single(UintSimplifiedType(UintTy::U64)), - U128 => single(UintSimplifiedType(UintTy::U128)), - F32 => single(FloatSimplifiedType(FloatTy::F32)), - F64 => single(FloatSimplifiedType(FloatTy::F64)), - Str => single(StrSimplifiedType), - Bool => single(BoolSimplifiedType), - Char => single(CharSimplifiedType), - Array => single(ArraySimplifiedType), - Slice => single(SliceSimplifiedType), + Isize => single(SimplifiedType::Int(IntTy::Isize)), + I8 => single(SimplifiedType::Int(IntTy::I8)), + I16 => single(SimplifiedType::Int(IntTy::I16)), + I32 => single(SimplifiedType::Int(IntTy::I32)), + I64 => single(SimplifiedType::Int(IntTy::I64)), + I128 => single(SimplifiedType::Int(IntTy::I128)), + Usize => single(SimplifiedType::Uint(UintTy::Usize)), + U8 => single(SimplifiedType::Uint(UintTy::U8)), + U16 => single(SimplifiedType::Uint(UintTy::U16)), + U32 => single(SimplifiedType::Uint(UintTy::U32)), + U64 => single(SimplifiedType::Uint(UintTy::U64)), + U128 => single(SimplifiedType::Uint(UintTy::U128)), + F32 => single(SimplifiedType::Float(FloatTy::F32)), + F64 => single(SimplifiedType::Float(FloatTy::F64)), + Str => single(SimplifiedType::Str), + Bool => single(SimplifiedType::Bool), + Char => single(SimplifiedType::Char), + Array => single(SimplifiedType::Array), + Slice => single(SimplifiedType::Slice), // FIXME: If we ever add an inherent impl for tuples // with different lengths, they won't show in rustdoc. // // Either manually update this arrayvec at this point // or start with a more complex refactoring. - Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(), - Unit => single(TupleSimplifiedType(0)), - RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(), - Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(), + Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(), + Unit => single(SimplifiedType::Tuple(0)), + RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(), + Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(), // FIXME: This will be wrong if we ever add inherent impls // for function pointers. - Fn => single(FunctionSimplifiedType(1)), - Never => single(NeverSimplifiedType), + Fn => single(SimplifiedType::Function(1)), + Never => single(SimplifiedType::Never), } }) } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 94b56304bcab4..e4906944c8d0a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -74,10 +74,10 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool { let lang_items = cx.tcx.lang_items(); // This list isn't complete, but good enough for our current list of paths. let incoherent_impls = [ - SimplifiedType::FloatSimplifiedType(FloatTy::F32), - SimplifiedType::FloatSimplifiedType(FloatTy::F64), - SimplifiedType::SliceSimplifiedType, - SimplifiedType::StrSimplifiedType, + SimplifiedType::Float(FloatTy::F32), + SimplifiedType::Float(FloatTy::F64), + SimplifiedType::Slice, + SimplifiedType::Str, ] .iter() .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied()); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 00e893fbdda8b..035511e891258 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -100,10 +100,7 @@ use rustc_middle::mir::ConstantKind; use rustc_middle::ty as rustc_ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; -use rustc_middle::ty::fast_reject::SimplifiedType::{ - ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType, - PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType, -}; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ BorrowKind, ClosureKind, FloatTy, IntTy, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UintTy, UpvarCapture, @@ -512,30 +509,30 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx> fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator + 'tcx { let ty = match name { - "bool" => BoolSimplifiedType, - "char" => CharSimplifiedType, - "str" => StrSimplifiedType, - "array" => ArraySimplifiedType, - "slice" => SliceSimplifiedType, + "bool" => SimplifiedType::Bool, + "char" => SimplifiedType::Char, + "str" => SimplifiedType::Str, + "array" => SimplifiedType::Array, + "slice" => SimplifiedType::Slice, // FIXME: rustdoc documents these two using just `pointer`. // // Maybe this is something we should do here too. - "const_ptr" => PtrSimplifiedType(Mutability::Not), - "mut_ptr" => PtrSimplifiedType(Mutability::Mut), - "isize" => IntSimplifiedType(IntTy::Isize), - "i8" => IntSimplifiedType(IntTy::I8), - "i16" => IntSimplifiedType(IntTy::I16), - "i32" => IntSimplifiedType(IntTy::I32), - "i64" => IntSimplifiedType(IntTy::I64), - "i128" => IntSimplifiedType(IntTy::I128), - "usize" => UintSimplifiedType(UintTy::Usize), - "u8" => UintSimplifiedType(UintTy::U8), - "u16" => UintSimplifiedType(UintTy::U16), - "u32" => UintSimplifiedType(UintTy::U32), - "u64" => UintSimplifiedType(UintTy::U64), - "u128" => UintSimplifiedType(UintTy::U128), - "f32" => FloatSimplifiedType(FloatTy::F32), - "f64" => FloatSimplifiedType(FloatTy::F64), + "const_ptr" => SimplifiedType::Ptr(Mutability::Not), + "mut_ptr" => SimplifiedType::Ptr(Mutability::Mut), + "isize" => SimplifiedType::Int(IntTy::Isize), + "i8" => SimplifiedType::Int(IntTy::I8), + "i16" => SimplifiedType::Int(IntTy::I16), + "i32" => SimplifiedType::Int(IntTy::I32), + "i64" => SimplifiedType::Int(IntTy::I64), + "i128" => SimplifiedType::Int(IntTy::I128), + "usize" => SimplifiedType::Uint(UintTy::Usize), + "u8" => SimplifiedType::Uint(UintTy::U8), + "u16" => SimplifiedType::Uint(UintTy::U16), + "u32" => SimplifiedType::Uint(UintTy::U32), + "u64" => SimplifiedType::Uint(UintTy::U64), + "u128" => SimplifiedType::Uint(UintTy::U128), + "f32" => SimplifiedType::Float(FloatTy::F32), + "f64" => SimplifiedType::Float(FloatTy::F64), _ => return [].iter().copied(), }; From 2d99f40ec5ee10df8f7325e4e71d8249f8dacd92 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Jul 2023 18:07:42 +0200 Subject: [PATCH 15/21] assembly: only consider blanket impls once --- .../src/solve/assembly/mod.rs | 273 +++++++++++++----- .../src/solve/project_goals.rs | 12 +- .../src/solve/trait_goals.rs | 9 +- ...mble-normalizing-self-ty-impl-ambiguity.rs | 25 ++ ...-normalizing-self-ty-impl-ambiguity.stderr | 23 ++ 5 files changed, 274 insertions(+), 68 deletions(-) create mode 100644 tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs create mode 100644 tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1e79899889551..73cf15ff94b59 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -10,9 +10,11 @@ use rustc_infer::traits::util::elaborate; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::CandidateKind; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; -use rustc_middle::ty::fast_reject::TreatProjections; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; +use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{fast_reject, TypeFoldable}; +use rustc_span::ErrorGuaranteed; use std::fmt::Debug; pub(super) mod structural_traits; @@ -109,10 +111,10 @@ pub(super) trait GoalKind<'tcx>: fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId; - // Try equating an assumption predicate against a goal's predicate. If it - // holds, then execute the `then` callback, which should do any additional - // work, then produce a response (typically by executing - // [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). + /// Try equating an assumption predicate against a goal's predicate. If it + /// holds, then execute the `then` callback, which should do any additional + /// work, then produce a response (typically by executing + /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -120,9 +122,9 @@ pub(super) trait GoalKind<'tcx>: then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx>; - // Consider a clause, which consists of a "assumption" and some "requirements", - // to satisfy a goal. If the requirements hold, then attempt to satisfy our - // goal by equating it with the assumption. + /// Consider a clause, which consists of a "assumption" and some "requirements", + /// to satisfy a goal. If the requirements hold, then attempt to satisfy our + /// goal by equating it with the assumption. fn consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -149,9 +151,9 @@ pub(super) trait GoalKind<'tcx>: }) } - // Consider a clause specifically for a `dyn Trait` self type. This requires - // additionally checking all of the supertraits and object bounds to hold, - // since they're not implied by the well-formedness of the object type. + /// Consider a clause specifically for a `dyn Trait` self type. This requires + /// additionally checking all of the supertraits and object bounds to hold, + /// since they're not implied by the well-formedness of the object type. fn consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -182,96 +184,106 @@ pub(super) trait GoalKind<'tcx>: impl_def_id: DefId, ) -> QueryResult<'tcx>; - // A type implements an `auto trait` if its components do as well. These components - // are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`]. + /// If the predicate contained an error, we want to avoid emitting unnecessary trait errors but + /// still want to emit errors for other trait goals. We have some special handling for this case. + /// + /// Trait goals always hold while projection goals never do. This is a bit arbitrary but prevents + /// incorrect normalization while hiding any trait errors. + fn consider_error_guaranteed_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + guar: ErrorGuaranteed, + ) -> QueryResult<'tcx>; + + /// A type implements an `auto trait` if its components do as well. These components + /// are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`]. fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A trait alias holds if the RHS traits and `where` clauses hold. + /// A trait alias holds if the RHS traits and `where` clauses hold. fn consider_trait_alias_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A type is `Copy` or `Clone` if its components are `Sized`. These components - // are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`]. + /// A type is `Copy` or `Clone` if its components are `Sized`. These components + /// are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`]. fn consider_builtin_sized_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These - // components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`]. + /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These + /// components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`]. fn consider_builtin_copy_clone_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A type is `PointerLike` if we can compute its layout, and that layout - // matches the layout of `usize`. + /// A type is `PointerLike` if we can compute its layout, and that layout + /// matches the layout of `usize`. fn consider_builtin_pointer_like_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A type is a `FnPtr` if it is of `FnPtr` type. + /// A type is a `FnPtr` if it is of `FnPtr` type. fn consider_builtin_fn_ptr_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn` - // family of traits where `A` is given by the signature of the type. + /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn` + /// family of traits where `A` is given by the signature of the type. fn consider_builtin_fn_trait_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, kind: ty::ClosureKind, ) -> QueryResult<'tcx>; - // `Tuple` is implemented if the `Self` type is a tuple. + /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // `Pointee` is always implemented. - // - // See the projection implementation for the `Metadata` types for all of - // the built-in types. For structs, the metadata type is given by the struct - // tail. + /// `Pointee` is always implemented. + /// + /// See the projection implementation for the `Metadata` types for all of + /// the built-in types. For structs, the metadata type is given by the struct + /// tail. fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A generator (that comes from an `async` desugaring) is known to implement - // `Future`, where `O` is given by the generator's return type - // that was computed during type-checking. + /// A generator (that comes from an `async` desugaring) is known to implement + /// `Future`, where `O` is given by the generator's return type + /// that was computed during type-checking. fn consider_builtin_future_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // A generator (that doesn't come from an `async` desugaring) is known to - // implement `Generator`, given the resume, yield, - // and return types of the generator computed during type-checking. + /// A generator (that doesn't come from an `async` desugaring) is known to + /// implement `Generator`, given the resume, yield, + /// and return types of the generator computed during type-checking. fn consider_builtin_generator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // The most common forms of unsizing are array to slice, and concrete (Sized) - // type into a `dyn Trait`. ADTs and Tuples can also have their final field - // unsized if it's generic. + /// The most common forms of unsizing are array to slice, and concrete (Sized) + /// type into a `dyn Trait`. ADTs and Tuples can also have their final field + /// unsized if it's generic. fn consider_builtin_unsize_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or - // if `Trait2` is a (transitive) supertrait of `Trait2`. + /// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or + /// if `Trait2` is a (transitive) supertrait of `Trait2`. fn consider_builtin_dyn_upcast_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -299,35 +311,60 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, ) -> Vec> { debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); + if let Some(ambig) = self.self_ty_infer_ambiguity_hack(goal) { + return ambig; + } + + let mut candidates = self.assemble_candidates_via_self_ty(goal); + + self.assemble_blanket_impl_candidates(goal, &mut candidates); + + self.assemble_param_env_candidates(goal, &mut candidates); - // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule, - // object bound, alias bound, etc. We are unable to determine this until we can at - // least structurally resolve the type one layer. - if goal.predicate.self_ty().is_ty_var() { - return vec![Candidate { + candidates + } + + fn self_ty_infer_ambiguity_hack>( + &mut self, + goal: Goal<'tcx, G>, + ) -> Option>> { + goal.predicate.self_ty().is_ty_var().then(|| { + vec![Candidate { source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity), result: self .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) .unwrap(), - }]; + }] + }) + } + + /// Assemble candidates which apply to the self type. This only looks at candidate which + /// apply to the specific self type and ignores all others. + /// + /// Returns `None` if the self type is still ambiguous. + fn assemble_candidates_via_self_ty>( + &mut self, + goal: Goal<'tcx, G>, + ) -> Vec> { + debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); + if let Some(ambig) = self.self_ty_infer_ambiguity_hack(goal) { + return ambig; } let mut candidates = Vec::new(); - self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates); - - self.assemble_impl_candidates(goal, &mut candidates); + self.assemble_non_blanket_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); - self.assemble_param_env_candidates(goal, &mut candidates); - self.assemble_alias_bound_candidates(goal, &mut candidates); self.assemble_object_bound_candidates(goal, &mut candidates); self.assemble_coherence_unknowable_candidates(goal, &mut candidates); + self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates); + candidates } @@ -385,7 +422,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // have a `Normalized` candidate. This doesn't work as long as we // use `CandidateSource` in winnowing. let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); - Ok(ecx.assemble_and_evaluate_candidates(goal)) + Ok(ecx.assemble_candidates_via_self_ty(goal)) }, ) }); @@ -396,22 +433,125 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } #[instrument(level = "debug", skip_all)] - fn assemble_impl_candidates>( + fn assemble_non_blanket_impl_candidates>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { let tcx = self.tcx(); - tcx.for_each_relevant_impl_treating_projections( - goal.predicate.trait_def_id(tcx), - goal.predicate.self_ty(), - TreatProjections::NextSolverLookup, - |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) { + let self_ty = goal.predicate.self_ty(); + let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); + let mut consider_impls_for_simplified_type = |simp| { + if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { + for &impl_def_id in impls_for_type { + match G::consider_impl_candidate(self, goal, impl_def_id) { + Ok(result) => candidates + .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), + Err(NoSolution) => (), + } + } + } + }; + + match self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::Generator(_, _, _) + | ty::Never + | ty::Tuple(_) => { + let simp = + fast_reject::simplify_type(tcx, self_ty, TreatParams::ForLookup).unwrap(); + consider_impls_for_simplified_type(simp); + } + + // HACK: For integer and float variables we have to manually look at all impls + // which have some integer or float as a self type. + ty::Infer(ty::IntVar(_)) => { + use ty::IntTy::*; + use ty::UintTy::*; + // This causes a compiler error if any new integer kinds are added. + let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; + let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; + let possible_integers = [ + // signed integers + SimplifiedType::Int(I8), + SimplifiedType::Int(I16), + SimplifiedType::Int(I32), + SimplifiedType::Int(I64), + SimplifiedType::Int(I128), + SimplifiedType::Int(Isize), + // unsigned integers + SimplifiedType::Uint(U8), + SimplifiedType::Uint(U16), + SimplifiedType::Uint(U32), + SimplifiedType::Uint(U64), + SimplifiedType::Uint(U128), + SimplifiedType::Uint(Usize), + ]; + for simp in possible_integers { + consider_impls_for_simplified_type(simp); + } + } + + ty::Infer(ty::FloatVar(_)) => { + // This causes a compiler error if any new float kinds are added. + let (ty::FloatTy::F32 | ty::FloatTy::F64); + let possible_floats = [ + SimplifiedType::Float(ty::FloatTy::F32), + SimplifiedType::Float(ty::FloatTy::F64), + ]; + + for simp in possible_floats { + consider_impls_for_simplified_type(simp); + } + } + + // The only traits applying to aliases and placeholders are blanket impls. + // + // Impls which apply to an alias after normalization are handled by + // `assemble_candidates_after_normalizing_self_ty`. + ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), + + // FIXME: These should ideally not exist as a self type. It would be nice for + // the builtin auto trait impls of generators should instead directly recurse + // into the witness. + ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(_, _) => (), + + // These variants should not exist as a self type. + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Param(_) + | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), + } + } + + fn assemble_blanket_impl_candidates>( + &mut self, + goal: Goal<'tcx, G>, + candidates: &mut Vec>, + ) { + let tcx = self.tcx(); + let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); + for &impl_def_id in trait_impls.blanket_impls() { + match G::consider_impl_candidate(self, goal, impl_def_id) { Ok(result) => candidates .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), Err(NoSolution) => (), - }, - ); + } + } } #[instrument(level = "debug", skip_all)] @@ -420,8 +560,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let lang_items = self.tcx().lang_items(); - let trait_def_id = goal.predicate.trait_def_id(self.tcx()); + let tcx = self.tcx(); + let lang_items = tcx.lang_items(); + let trait_def_id = goal.predicate.trait_def_id(tcx); // N.B. When assembling built-in candidates for lang items that are also // `auto` traits, then the auto trait candidate that is assembled in @@ -430,9 +571,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // Instead of adding the logic here, it's a better idea to add it in // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in // `solve::trait_goals` instead. - let result = if self.tcx().trait_is_auto(trait_def_id) { + let result = if let Err(guar) = goal.predicate.error_reported() { + G::consider_error_guaranteed_candidate(self, guar) + } else if tcx.trait_is_auto(trait_def_id) { G::consider_auto_trait_candidate(self, goal) - } else if self.tcx().trait_is_alias(trait_def_id) { + } else if tcx.trait_is_alias(trait_def_id) { G::consider_trait_alias_candidate(self, goal) } else if lang_items.sized_trait() == Some(trait_def_id) { G::consider_builtin_sized_candidate(self, goal) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index d677fbdc7f425..222ed9939ba24 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -2,7 +2,6 @@ use crate::traits::specialization_graph; use super::assembly::{self, structural_traits}; use super::EvalCtxt; -use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; @@ -15,7 +14,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::ProjectionPredicate; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; impl<'tcx> EvalCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self), ret)] @@ -246,6 +245,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { }) } + /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error` + /// and succeed. Can experiment with this to figure out what results in better error messages. + fn consider_error_guaranteed_candidate( + _ecx: &mut EvalCtxt<'_, 'tcx>, + _guar: ErrorGuaranteed, + ) -> QueryResult<'tcx> { + Err(NoSolution) + } + fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 29889614620dd..930e62d638831 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -11,7 +11,7 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; -use rustc_span::DUMMY_SP; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn self_ty(self) -> Ty<'tcx> { @@ -78,6 +78,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }) } + fn consider_error_guaranteed_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + _guar: ErrorGuaranteed, + ) -> QueryResult<'tcx> { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs new file mode 100644 index 0000000000000..727ce84ba3591 --- /dev/null +++ b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs @@ -0,0 +1,25 @@ +// compile-flags: -Ztrait-solver=next + +// Checks that we do not get ambiguity by considering an impl +// multiple times if we're able to normalize the self type. +trait Trait<'a> {} + +impl<'a, T: 'a> Trait<'a> for T {} + +fn impls_trait<'a, T: Trait<'a>>() {} + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + +fn call() { + impls_trait::<::Assoc>(); +} + +fn main() { + call::<()>(); + impls_trait::<<<() as Id>::Assoc as Id>::Assoc>(); +} diff --git a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr new file mode 100644 index 0000000000000..91b635b35eb6c --- /dev/null +++ b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed: cannot satisfy `::Assoc: Trait<'_>` + --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:19:5 + | +LL | impls_trait::<::Assoc>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `::Assoc: Trait<'_>` +note: required by a bound in `impls_trait` + --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:9:23 + | +LL | fn impls_trait<'a, T: Trait<'a>>() {} + | ^^^^^^^^^ required by this bound in `impls_trait` + +error[E0282]: type annotations needed + --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:24:5 + | +LL | impls_trait::<<<() as Id>::Assoc as Id>::Assoc>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_trait` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. From aa28b77b5a362a70e4c1e4f99047f903f735954d Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Jul 2023 18:15:14 +0200 Subject: [PATCH 16/21] add FIXME --- compiler/rustc_middle/src/ty/fast_reject.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index deb4dcf1f760a..668aa4521c101 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -62,6 +62,9 @@ pub enum TreatParams { /// correct mode for *lookup*, as during candidate selection. /// /// N.B. during deep rejection, this acts identically to `ForLookup`. + /// + /// FIXME(-Ztrait-solver=next): Remove this variant and cleanup + /// the code. NextSolverLookup, } From 7c97a76b76120bd982762a982d4254ece32c43dc Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Jul 2023 18:18:32 +0200 Subject: [PATCH 17/21] re-add comment --- compiler/rustc_trait_selection/src/solve/assembly/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 73cf15ff94b59..68e931aac8c12 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -324,6 +324,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates } + /// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule, + /// object bound, alias bound, etc. We are unable to determine this until we can at + /// least structurally resolve the type one layer. + /// + /// It would also require us to consider all impls of the trait, which is both pretty + /// bad for perf and would also constrain the self type if there is just a single impl. fn self_ty_infer_ambiguity_hack>( &mut self, goal: Goal<'tcx, G>, From 7de9b654b7888ee387a9907f7a5f9b824ca053be Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Jul 2023 17:42:59 +0000 Subject: [PATCH 18/21] Avoid another gha group nesting --- src/bootstrap/test.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 44b8c2d8c013b..c69b21488d23d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -2087,10 +2087,11 @@ impl Step for ErrorIndex { let mut tool = tool::ErrorIndex::command(builder); tool.arg("markdown").arg(&output); - let _guard = + let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = util::timeit(&builder); builder.run_quiet(&mut tool); + drop(guard); // The tests themselves need to link to std, so make sure it is // available. builder.ensure(compile::Std::new(compiler, compiler.host)); From d97ec97b9486fe5798938e6842bda2385e906cbc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 20 Jul 2023 09:51:47 +0000 Subject: [PATCH 19/21] Don't translate compiler-internal bug messages --- compiler/rustc_errors/src/lib.rs | 14 +++--- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 3 +- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 49 ++++++------------- compiler/rustc_session/src/session.rs | 2 +- 6 files changed, 27 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 31410c39d368e..1da02e1bb012f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1003,7 +1003,7 @@ impl Handler { self.emit_diag_at_span(Diagnostic::new_with_code(Warning(None), Some(code), msg), span); } - pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { + pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { self.inner.borrow_mut().span_bug(span, msg) } @@ -1012,7 +1012,7 @@ impl Handler { pub fn delay_span_bug( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> ErrorGuaranteed { self.inner.borrow_mut().delay_span_bug(span, msg) } @@ -1596,8 +1596,8 @@ impl HandlerInner { } #[track_caller] - fn span_bug(&mut self, sp: impl Into, msg: impl Into) -> ! { - self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp); + fn span_bug(&mut self, sp: impl Into, msg: impl Into) -> ! { + self.emit_diag_at_span(Diagnostic::new(Bug, msg.into()), sp); panic::panic_any(ExplicitBug); } @@ -1610,7 +1610,7 @@ impl HandlerInner { fn delay_span_bug( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> ErrorGuaranteed { // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before // incrementing `err_count` by one, so we need to +1 the comparing. @@ -1619,9 +1619,9 @@ impl HandlerInner { self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() }) { // FIXME: don't abort here if report_delayed_bugs is off - self.span_bug(sp, msg); + self.span_bug(sp, msg.into()); } - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into()); diagnostic.set_span(sp.into()); self.emit_diagnostic(&mut diagnostic).unwrap() } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 4b0907cf15a65..12473a2bb0bdd 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1147,7 +1147,7 @@ impl<'a> ExtCtxt<'a> { pub fn span_warn>(&self, sp: S, msg: impl Into) { self.sess.parse_sess.span_diagnostic.span_warn(sp, msg); } - pub fn span_bug>(&self, sp: S, msg: impl Into) -> ! { + pub fn span_bug>(&self, sp: S, msg: impl Into) -> ! { self.sess.parse_sess.span_diagnostic.span_bug(sp, msg); } pub fn trace_macros_diag(&mut self) { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cdb0b2240a47b..f9c1ca9a8b167 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -15,7 +15,6 @@ use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; -use rustc_error_messages::DiagnosticMessage; use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -1991,7 +1990,7 @@ impl<'tcx> Ty<'tcx> { pub fn new_error_with_message>( tcx: TyCtxt<'tcx>, span: S, - msg: impl Into, + msg: impl Into, ) -> Ty<'tcx> { let reported = tcx.sess.delay_span_bug(span, msg); Ty::new(tcx, Error(reported)) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8455803ad0c5f..c3cf6437afa07 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -247,7 +247,7 @@ impl<'a> Parser<'a> { self.sess.span_diagnostic.struct_span_err(sp, m) } - pub fn span_bug>(&self, sp: S, m: impl Into) -> ! { + pub fn span_bug>(&self, sp: S, m: impl Into) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index fdf365178474d..14891c45d81a2 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -8,7 +8,6 @@ use crate::errors::{ TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, }; -use crate::fluent_generated as fluent; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; @@ -214,41 +213,25 @@ impl<'a> Parser<'a> { if let PatKind::Or(pats) = &pat.kind { let span = pat.span; - - if trailing_vert { - // We already emitted an error and suggestion to remove the trailing vert. Don't - // emit again. - - // FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to - // `delay_span_bug()` instead of fluent message - self.sess.span_diagnostic.delay_span_bug( - span, - match syntax_loc { - PatternLocation::LetBinding => { - fluent::parse_or_pattern_not_allowed_in_let_binding - } - PatternLocation::FunctionParameter => { - fluent::parse_or_pattern_not_allowed_in_fn_parameters - } - }, - ); + let pat = pprust::pat_to_string(&pat); + let sub = if pats.len() == 1 { + Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat }) } else { - let pat = pprust::pat_to_string(&pat); - let sub = if pats.len() == 1 { - Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat }) - } else { - Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat }) - }; + Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat }) + }; - self.sess.emit_err(match syntax_loc { - PatternLocation::LetBinding => { - TopLevelOrPatternNotAllowed::LetBinding { span, sub } - } - PatternLocation::FunctionParameter => { - TopLevelOrPatternNotAllowed::FunctionParameter { span, sub } - } - }); + let mut err = self.sess.create_err(match syntax_loc { + PatternLocation::LetBinding => { + TopLevelOrPatternNotAllowed::LetBinding { span, sub } + } + PatternLocation::FunctionParameter => { + TopLevelOrPatternNotAllowed::FunctionParameter { span, sub } + } + }); + if trailing_vert { + err.delay_as_bug(); } + err.emit(); } Ok((pat, colon)) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 0f5d3b291db75..146bb11bd3a7b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -677,7 +677,7 @@ impl Session { pub fn delay_span_bug>( &self, sp: S, - msg: impl Into, + msg: impl Into, ) -> ErrorGuaranteed { self.diagnostic().delay_span_bug(sp, msg) } From 2062f2ca8261b521caa9c34c195bf472dcb59e98 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Jul 2023 10:40:59 +0200 Subject: [PATCH 20/21] review --- .../src/solve/assembly/mod.rs | 8 +++---- ...mble-normalizing-self-ty-impl-ambiguity.rs | 2 ++ ...-normalizing-self-ty-impl-ambiguity.stderr | 23 ------------------- .../dont-normalize-proj-with-error.rs | 22 ++++++++++++++++++ .../dont-normalize-proj-with-error.stderr | 9 ++++++++ 5 files changed, 37 insertions(+), 27 deletions(-) delete mode 100644 tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr create mode 100644 tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs create mode 100644 tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 68e931aac8c12..b661ff481a0a8 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -311,7 +311,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, ) -> Vec> { debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); - if let Some(ambig) = self.self_ty_infer_ambiguity_hack(goal) { + if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) { return ambig; } @@ -324,13 +324,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates } - /// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule, + /// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule, /// object bound, alias bound, etc. We are unable to determine this until we can at /// least structurally resolve the type one layer. /// /// It would also require us to consider all impls of the trait, which is both pretty /// bad for perf and would also constrain the self type if there is just a single impl. - fn self_ty_infer_ambiguity_hack>( + fn assemble_self_ty_infer_ambiguity_response>( &mut self, goal: Goal<'tcx, G>, ) -> Option>> { @@ -353,7 +353,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, ) -> Vec> { debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); - if let Some(ambig) = self.self_ty_infer_ambiguity_hack(goal) { + if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) { return ambig; } diff --git a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs index 727ce84ba3591..826e8c1e0b131 100644 --- a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs +++ b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs @@ -1,7 +1,9 @@ // compile-flags: -Ztrait-solver=next +// check-pass // Checks that we do not get ambiguity by considering an impl // multiple times if we're able to normalize the self type. + trait Trait<'a> {} impl<'a, T: 'a> Trait<'a> for T {} diff --git a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr deleted file mode 100644 index 91b635b35eb6c..0000000000000 --- a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0283]: type annotations needed: cannot satisfy `::Assoc: Trait<'_>` - --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:19:5 - | -LL | impls_trait::<::Assoc>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: cannot satisfy `::Assoc: Trait<'_>` -note: required by a bound in `impls_trait` - --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:9:23 - | -LL | fn impls_trait<'a, T: Trait<'a>>() {} - | ^^^^^^^^^ required by this bound in `impls_trait` - -error[E0282]: type annotations needed - --> $DIR/assemble-normalizing-self-ty-impl-ambiguity.rs:24:5 - | -LL | impls_trait::<<<() as Id>::Assoc as Id>::Assoc>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_trait` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs new file mode 100644 index 0000000000000..19a6fa990ff14 --- /dev/null +++ b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs @@ -0,0 +1,22 @@ +// compile-flags: -Ztrait-solver=next + +// Test that we don't incorrectly leak unconstrained inference variables +// if the projection contained an error. This caused an ICE in writeback. + +trait Mirror { + type Assoc: ?Sized; +} + +struct Wrapper(T); +impl Mirror for Wrapper { + type Assoc = T; +} + +fn mirror(_: W) -> Box { todo!() } + +fn type_error() -> TypeError { todo!() } +//~^ ERROR cannot find type `TypeError` in this scope + +fn main() { + let x = mirror(type_error()); +} diff --git a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr new file mode 100644 index 0000000000000..5a7459ec1fdee --- /dev/null +++ b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `TypeError` in this scope + --> $DIR/dont-normalize-proj-with-error.rs:17:20 + | +LL | fn type_error() -> TypeError { todo!() } + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From 5c75bc5317b4326bdc3d8a4708d0602bd0ec219d Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Jul 2023 11:26:22 +0200 Subject: [PATCH 21/21] update doc comments --- .../src/solve/assembly/mod.rs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index b661ff481a0a8..6920e790e71ae 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -184,18 +184,21 @@ pub(super) trait GoalKind<'tcx>: impl_def_id: DefId, ) -> QueryResult<'tcx>; - /// If the predicate contained an error, we want to avoid emitting unnecessary trait errors but - /// still want to emit errors for other trait goals. We have some special handling for this case. + /// If the predicate contained an error, we want to avoid emitting unnecessary trait + /// errors but still want to emit errors for other trait goals. We have some special + /// handling for this case. /// - /// Trait goals always hold while projection goals never do. This is a bit arbitrary but prevents - /// incorrect normalization while hiding any trait errors. + /// Trait goals always hold while projection goals never do. This is a bit arbitrary + /// but prevents incorrect normalization while hiding any trait errors. fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, guar: ErrorGuaranteed, ) -> QueryResult<'tcx>; - /// A type implements an `auto trait` if its components do as well. These components - /// are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`]. + /// A type implements an `auto trait` if its components do as well. + /// + /// These components are given by built-in rules from + /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`]. fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -207,15 +210,19 @@ pub(super) trait GoalKind<'tcx>: goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - /// A type is `Copy` or `Clone` if its components are `Sized`. These components - /// are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`]. + /// A type is `Copy` or `Clone` if its components are `Sized`. + /// + /// These components are given by built-in rules from + /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`]. fn consider_builtin_sized_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These - /// components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`]. + /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. + /// + /// These components are given by built-in rules from + /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`]. fn consider_builtin_copy_clone_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>,