diff options
| author | Ralf Jung <post@ralfj.de> | 2024-05-19 10:35:44 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-05-19 10:35:44 +0200 |
| commit | 3460853a453fb85a13ef6763ae01b2e64c9be7b7 (patch) | |
| tree | fa91aa22e7d5b09dde4b55bbc4bb6c926bf8a2f2 | |
| parent | 1ba83f2dc11ce0f2249e597bb59839bb8ea8df6b (diff) | |
| parent | 6579ed89f0fcc26da71afdd11d30d63f6f812a0a (diff) | |
| download | rust-3460853a453fb85a13ef6763ae01b2e64c9be7b7.tar.gz rust-3460853a453fb85a13ef6763ae01b2e64c9be7b7.zip | |
Merge from rustc
340 files changed, 5379 insertions, 2298 deletions
diff --git a/Cargo.lock b/Cargo.lock index df4e4f32613..186892af21c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4343,6 +4343,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_index", "rustc_macros", + "rustc_next_trait_solver", "rustc_query_system", "rustc_serialize", "rustc_session", @@ -4451,7 +4452,13 @@ dependencies = [ name = "rustc_next_trait_solver" version = "0.0.0" dependencies = [ + "derivative", + "rustc_ast_ir", + "rustc_data_structures", + "rustc_macros", + "rustc_serialize", "rustc_type_ir", + "rustc_type_ir_macros", ] [[package]] @@ -4752,6 +4759,7 @@ name = "rustc_trait_selection" version = "0.0.0" dependencies = [ "bitflags 2.5.0", + "derivative", "itertools 0.12.1", "rustc_ast", "rustc_ast_ir", @@ -4767,10 +4775,13 @@ dependencies = [ "rustc_next_trait_solver", "rustc_parse_format", "rustc_query_system", + "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", "rustc_transmute", + "rustc_type_ir", + "rustc_type_ir_macros", "smallvec", "tracing", ] diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index c57be5d1106..a95ef4c460f 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -2,7 +2,6 @@ use std::borrow::{Borrow, Cow}; use std::cmp; use std::fmt::{self, Write}; use std::iter; -use std::num::NonZero; use std::ops::Bound; use std::ops::Deref; @@ -11,8 +10,8 @@ use tracing::debug; use crate::{ Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche, - Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, Variants, - WrappingRange, + NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, + Variants, WrappingRange, }; // A variant is absent if it's uninhabited and only has ZST fields. @@ -328,7 +327,7 @@ pub trait LayoutCalculator { Some(LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, - fields: FieldsShape::Union(NonZero::new(only_variant.len())?), + fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?), abi, largest_niche: None, align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 9f2788c87c3..53aa8ad7cca 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -4,7 +4,7 @@ #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] use std::fmt; -use std::num::{NonZero, ParseIntError}; +use std::num::{NonZeroUsize, ParseIntError}; use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub}; use std::str::FromStr; @@ -1175,7 +1175,7 @@ pub enum FieldsShape<FieldIdx: Idx> { Primitive, /// All fields start at no offset. The `usize` is the field count. - Union(NonZero<usize>), + Union(NonZeroUsize), /// Array/vector-like placement, with all fields of identical types. Array { stride: Size, count: u64 }, diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 14e04774788..5d37bbd689f 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2105,7 +2105,7 @@ impl Ty { #[derive(Clone, Encodable, Decodable, Debug)] pub struct BareFnTy { - pub unsafety: Unsafe, + pub safety: Safety, pub ext: Extern, pub generic_params: ThinVec<GenericParam>, pub decl: P<FnDecl>, @@ -2484,11 +2484,15 @@ pub enum IsAuto { No, } +/// Safety of items. #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)] #[derive(HashStable_Generic)] -pub enum Unsafe { - Yes(Span), - No, +pub enum Safety { + /// `unsafe` an item is explicitly marked as `unsafe`. + Unsafe(Span), + /// Default means no value was provided, it will take a default value given the context in + /// which is used. + Default, } /// Describes what kind of coroutine markers, if any, a function has. @@ -2692,7 +2696,7 @@ pub struct ModSpans { pub struct ForeignMod { /// `unsafe` keyword accepted syntactically for macro DSLs, but not /// semantically by Rust. - pub unsafety: Unsafe, + pub safety: Safety, pub abi: Option<StrLit>, pub items: ThinVec<P<ForeignItem>>, } @@ -3011,8 +3015,8 @@ impl Extern { /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct FnHeader { - /// The `unsafe` keyword, if any - pub unsafety: Unsafe, + /// Whether this is `unsafe`, or has a default safety + pub safety: Safety, /// Whether this is `async`, `gen`, or nothing. pub coroutine_kind: Option<CoroutineKind>, /// The `const` keyword, if any @@ -3024,8 +3028,8 @@ pub struct FnHeader { impl FnHeader { /// Does this function header have any qualifiers or is it empty? pub fn has_qualifiers(&self) -> bool { - let Self { unsafety, coroutine_kind, constness, ext } = self; - matches!(unsafety, Unsafe::Yes(_)) + let Self { safety, coroutine_kind, constness, ext } = self; + matches!(safety, Safety::Unsafe(_)) || coroutine_kind.is_some() || matches!(constness, Const::Yes(_)) || !matches!(ext, Extern::None) @@ -3035,7 +3039,7 @@ impl FnHeader { impl Default for FnHeader { fn default() -> FnHeader { FnHeader { - unsafety: Unsafe::No, + safety: Safety::Default, coroutine_kind: None, constness: Const::No, ext: Extern::None, @@ -3045,7 +3049,7 @@ impl Default for FnHeader { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Trait { - pub unsafety: Unsafe, + pub safety: Safety, pub is_auto: IsAuto, pub generics: Generics, pub bounds: GenericBounds, @@ -3101,7 +3105,7 @@ pub struct TyAlias { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Impl { pub defaultness: Defaultness, - pub unsafety: Unsafe, + pub safety: Safety, pub generics: Generics, pub constness: Const, pub polarity: ImplPolarity, @@ -3209,7 +3213,7 @@ pub enum ItemKind { /// E.g., `mod foo;` or `mod foo { .. }`. /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not /// semantically by Rust. - Mod(Unsafe, ModKind), + Mod(Safety, ModKind), /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 1cfb8972a62..566b20c490e 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -499,8 +499,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { vis.visit_mt(mt); } TyKind::BareFn(bft) => { - let BareFnTy { unsafety, ext: _, generic_params, decl, decl_span } = bft.deref_mut(); - visit_unsafety(unsafety, vis); + let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut(); + visit_safety(safety, vis); generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); vis.visit_span(decl_span); @@ -543,8 +543,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { } fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) { - let ForeignMod { unsafety, abi: _, items } = foreign_mod; - visit_unsafety(unsafety, vis); + let ForeignMod { safety, abi: _, items } = foreign_mod; + visit_safety(safety, vis); items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } @@ -859,10 +859,10 @@ fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -fn visit_unsafety<T: MutVisitor>(unsafety: &mut Unsafe, vis: &mut T) { - match unsafety { - Unsafe::Yes(span) => vis.visit_span(span), - Unsafe::No => {} +fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) { + match safety { + Safety::Unsafe(span) => vis.visit_span(span), + Safety::Default => {} } } @@ -1092,8 +1092,8 @@ impl NoopVisitItemKind for ItemKind { vis.visit_generics(generics); visit_opt(body, |body| vis.visit_block(body)); } - ItemKind::Mod(unsafety, mod_kind) => { - visit_unsafety(unsafety, vis); + ItemKind::Mod(safety, mod_kind) => { + visit_safety(safety, vis); match mod_kind { ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => { vis.visit_span(inner_span); @@ -1130,7 +1130,7 @@ impl NoopVisitItemKind for ItemKind { } ItemKind::Impl(box Impl { defaultness, - unsafety, + safety, generics, constness, polarity, @@ -1139,7 +1139,7 @@ impl NoopVisitItemKind for ItemKind { items, }) => { visit_defaultness(defaultness, vis); - visit_unsafety(unsafety, vis); + visit_safety(safety, vis); vis.visit_generics(generics); visit_constness(constness, vis); visit_polarity(polarity, vis); @@ -1147,8 +1147,8 @@ impl NoopVisitItemKind for ItemKind { vis.visit_ty(self_ty); items.flat_map_in_place(|item| vis.flat_map_impl_item(item)); } - ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => { - visit_unsafety(unsafety, vis); + ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => { + visit_safety(safety, vis); vis.visit_generics(generics); visit_bounds(bounds, vis); items.flat_map_in_place(|item| vis.flat_map_trait_item(item)); @@ -1254,10 +1254,10 @@ fn visit_const_item<T: MutVisitor>( } fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety, coroutine_kind, constness, ext: _ } = header; + let FnHeader { safety, coroutine_kind, constness, ext: _ } = header; visit_constness(constness, vis); coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); - visit_unsafety(unsafety, vis); + visit_safety(safety, vis); } pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d00352ea2e1..099a6096d0b 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -881,6 +881,8 @@ pub enum NonterminalKind { }, PatWithOr, Expr, + /// Matches an expression using the rules from edition 2021 and earlier. + Expr2021, Ty, Ident, Lifetime, @@ -910,6 +912,7 @@ impl NonterminalKind { }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, + sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -929,6 +932,7 @@ impl NonterminalKind { NonterminalKind::PatParam { inferred: false } => sym::pat_param, NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, NonterminalKind::Expr => sym::expr, + NonterminalKind::Expr2021 => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7794edc3505..93de42b55cc 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -366,7 +366,7 @@ impl WalkItemKind for ItemKind { } ItemKind::Impl(box Impl { defaultness: _, - unsafety: _, + safety: _, generics, constness: _, polarity: _, @@ -384,7 +384,7 @@ impl WalkItemKind for ItemKind { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => { + ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => { try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index a1e5c275c18..27f8a6eae02 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -188,7 +188,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Asyncness::No => hir::IsAsync::NotAsync, }; hir::FnHeader { - unsafety: sig.unsafety, + safety: sig.safety, constness: self.tcx.constness(sig_id), asyncness, abi: sig.abi, @@ -341,7 +341,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn generate_header_error(&self) -> hir::FnHeader { hir::FnHeader { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, abi: abi::Abi::Rust, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1255c1bba08..a15449409df 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Union(vdata, generics) } ItemKind::Impl(box Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)), }; hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - unsafety: self.lower_unsafety(*unsafety), + safety: self.lower_safety(*safety), polarity, defaultness, defaultness_span, @@ -398,14 +398,14 @@ impl<'hir> LoweringContext<'_, 'hir> { items: new_impl_items, })) } - ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => { + ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { // FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible let constness = attrs .unwrap_or(&[]) .iter() .find(|x| x.has_name(sym::const_trait)) .map_or(Const::No, |x| Const::Yes(x.span)); - let (generics, (unsafety, items, bounds)) = self.lower_generics( + let (generics, (safety, items, bounds)) = self.lower_generics( generics, constness, id, @@ -418,11 +418,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), ); - let unsafety = this.lower_unsafety(*unsafety); - (unsafety, items, bounds) + let safety = this.lower_safety(*safety); + (safety, items, bounds) }, ); - hir::ItemKind::Trait(*is_auto, unsafety, generics, bounds, items) + hir::ItemKind::Trait(*is_auto, safety, generics, bounds, items) } ItemKind::TraitAlias(generics, bounds) => { let (generics, bounds) = self.lower_generics( @@ -1360,7 +1360,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::IsAsync::NotAsync }; hir::FnHeader { - unsafety: self.lower_unsafety(h.unsafety), + safety: self.lower_safety(h.safety), asyncness: asyncness, constness: self.lower_constness(h.constness), abi: self.lower_extern(h.ext), @@ -1410,10 +1410,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - pub(super) fn lower_unsafety(&mut self, u: Unsafe) -> hir::Unsafety { - match u { - Unsafe::Yes(_) => hir::Unsafety::Unsafe, - Unsafe::No => hir::Unsafety::Normal, + pub(super) fn lower_safety(&mut self, s: Safety) -> hir::Safety { + match s { + Safety::Unsafe(_) => hir::Safety::Unsafe, + Safety::Default => hir::Safety::Safe, } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c23da8aa01e..a9af5ad7459 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1324,7 +1324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { generic_params, - unsafety: self.lower_unsafety(f.unsafety), + safety: self.lower_safety(f.safety), abi: self.lower_extern(f.ext), decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 172e97e7271..9d07683f8d6 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -521,7 +521,7 @@ impl<'a> AstValidator<'a> { fn check_foreign_fn_headerless( &self, // Deconstruct to ensure exhaustiveness - FnHeader { unsafety, coroutine_kind, constness, ext }: FnHeader, + FnHeader { safety, coroutine_kind, constness, ext }: FnHeader, ) { let report_err = |span| { self.dcx().emit_err(errors::FnQualifierInExtern { @@ -529,9 +529,9 @@ impl<'a> AstValidator<'a> { block: self.current_extern_span(), }); }; - match unsafety { - Unsafe::Yes(span) => report_err(span), - Unsafe::No => (), + match safety { + Safety::Unsafe(span) => report_err(span), + Safety::Default => (), } match coroutine_kind { Some(knd) => report_err(knd.span()), @@ -592,7 +592,7 @@ impl<'a> AstValidator<'a> { (Some(FnCtxt::Free), Some(header)) => match header.ext { Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _) | Extern::Implicit(_) - if matches!(header.unsafety, Unsafe::Yes(_)) => + if matches!(header.safety, Safety::Unsafe(_)) => { return; } @@ -891,7 +891,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match &item.kind { ItemKind::Impl(box Impl { - unsafety, + safety, polarity, defaultness: _, constness, @@ -910,7 +910,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // which isn't allowed. Not a problem for this obscure, obsolete syntax. this.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span }); } - if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity) + if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity) { this.dcx().emit_err(errors::UnsafeNegativeImpl { span: sp.to(t.path.span), @@ -933,7 +933,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { return; // Avoid visiting again. } ItemKind::Impl(box Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -956,7 +956,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { &item.vis, errors::VisibilityNotPermittedNote::IndividualImplItems, ); - if let &Unsafe::Yes(span) = unsafety { + if let &Safety::Unsafe(span) = safety { this.dcx().emit_err(errors::InherentImplCannotUnsafe { span: self_ty.span, annotation_span: span, @@ -1020,13 +1020,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } - ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => { + ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - if let &Unsafe::Yes(span) = unsafety { + if let &Safety::Unsafe(span) = safety { self.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); } if abi.is_none() { @@ -1078,8 +1078,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again } - ItemKind::Mod(unsafety, mod_kind) => { - if let &Unsafe::Yes(span) = unsafety { + ItemKind::Mod(safety, mod_kind) => { + if let &Safety::Unsafe(span) = safety { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index defb666e2b6..545b98a9135 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -524,7 +524,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere } } - fn peek_comment<'b>(&'b self) -> Option<&'b Comment> where 'a: 'b { + fn peek_comment<'b>(&'b self) -> Option<&'b Comment> + where + 'a: 'b, + { self.comments().and_then(|c| c.peek()) } @@ -1150,7 +1153,7 @@ impl<'a> State<'a> { self.pclose(); } ast::TyKind::BareFn(f) => { - self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params); + self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params); } ast::TyKind::Path(None, path) => { self.print_path(path, false, 0); @@ -1908,7 +1911,7 @@ impl<'a> State<'a> { fn print_ty_fn( &mut self, ext: ast::Extern, - unsafety: ast::Unsafe, + safety: ast::Safety, decl: &ast::FnDecl, name: Option<Ident>, generic_params: &[ast::GenericParam], @@ -1924,7 +1927,7 @@ impl<'a> State<'a> { }, span: DUMMY_SP, }; - let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() }; + let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() }; self.print_fn(decl, header, name, &generics); self.end(); } @@ -1932,7 +1935,7 @@ impl<'a> State<'a> { fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); header.coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind)); - self.print_unsafety(header.unsafety); + self.print_safety(header.safety); match header.ext { ast::Extern::None => {} @@ -1949,10 +1952,10 @@ impl<'a> State<'a> { self.word("fn") } - fn print_unsafety(&mut self, s: ast::Unsafe) { + fn print_safety(&mut self, s: ast::Safety) { match s { - ast::Unsafe::No => {} - ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"), + ast::Safety::Default => {} + ast::Safety::Unsafe(_) => self.word_nbsp("unsafe"), } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 16c3ee948a4..59d9b0c1a8e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -198,10 +198,10 @@ impl<'a> State<'a> { &item.attrs, ); } - ast::ItemKind::Mod(unsafety, mod_kind) => { + ast::ItemKind::Mod(safety, mod_kind) => { self.head(Self::to_string(|s| { s.print_visibility(&item.vis); - s.print_unsafety(*unsafety); + s.print_safety(*safety); s.word("mod"); })); self.print_ident(item.ident); @@ -226,7 +226,7 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(nmod) => { self.head(Self::to_string(|s| { - s.print_unsafety(nmod.unsafety); + s.print_safety(nmod.safety); s.word("extern"); })); if let Some(abi) = nmod.abi { @@ -275,7 +275,7 @@ impl<'a> State<'a> { self.print_struct(struct_def, generics, item.ident, item.span, true); } ast::ItemKind::Impl(box ast::Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -287,7 +287,7 @@ impl<'a> State<'a> { self.head(""); self.print_visibility(&item.vis); self.print_defaultness(*defaultness); - self.print_unsafety(*unsafety); + self.print_safety(*safety); self.word("impl"); if generics.params.is_empty() { @@ -323,7 +323,7 @@ impl<'a> State<'a> { } ast::ItemKind::Trait(box ast::Trait { is_auto, - unsafety, + safety, generics, bounds, items, @@ -331,7 +331,7 @@ impl<'a> State<'a> { }) => { self.head(""); self.print_visibility(&item.vis); - self.print_unsafety(*unsafety); + self.print_safety(*safety); self.print_is_auto(*is_auto); self.word_nbsp("trait"); self.print_ident(item.ident); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index ccc45e2829a..15050c87b39 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -24,8 +24,8 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt, - TypeSuperVisitable, TypeVisitor, + self, suggest_constraining_type_params, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitor, Upcast, }; use rustc_middle::util::CallKind; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; @@ -1915,7 +1915,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.infcx.err_ctxt().suggest_derive( &obligation, err, - trait_ref.to_predicate(self.infcx.tcx), + trait_ref.upcast(self.infcx.tcx), ); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c9a09c19ce6..35017b9e6b5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -9,7 +9,7 @@ use rustc_hir::{self as hir, BindingMode, ByRef, Node}; use rustc_infer::traits; use rustc_middle::bug; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; -use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast}; use rustc_middle::{ hir::place::PlaceBase, mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location}, @@ -1255,7 +1255,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.infcx.err_ctxt().suggest_derive( &obligation, err, - trait_ref.to_predicate(self.infcx.tcx), + trait_ref.upcast(self.infcx.tcx), ); } Some(errors) => { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d8d582b0ad1..8112fb7b89c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1098,7 +1098,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { liberated_sig.inputs().iter().copied(), peeled_ty, liberated_sig.c_variadic, - hir::Unsafety::Normal, + hir::Safety::Safe, rustc_target::spec::abi::Abi::Rust, )), ); diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 49d3f7381d9..2dc2568cd47 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -4,7 +4,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::canonical::Canonical; use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast}; use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; @@ -115,7 +115,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn prove_predicates( &mut self, - predicates: impl IntoIterator<Item: ToPredicate<'tcx> + std::fmt::Debug>, + predicates: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + std::fmt::Debug>, locations: Locations, category: ConstraintCategory<'tcx>, ) { @@ -127,12 +127,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(super) fn prove_predicate( &mut self, - predicate: impl ToPredicate<'tcx> + std::fmt::Debug, + predicate: impl Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + std::fmt::Debug, locations: Locations, category: ConstraintCategory<'tcx>, ) { let param_env = self.param_env; - let predicate = predicate.to_predicate(self.tcx()); + let predicate = predicate.upcast(self.tcx()); let _: Result<_, ErrorGuaranteed> = self.fully_perform_op( locations, category, diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 4e45dc42aa7..741ec05dc9a 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -98,7 +98,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_provided_sig.inputs().iter().copied(), output_ty, user_provided_sig.c_variadic, - user_provided_sig.unsafety, + user_provided_sig.safety, user_provided_sig.abi, ); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 2740e9689c5..6cf9ac45aa3 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2007,13 +2007,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => { + CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(safety)) => { let sig = match op.ty(body, tcx).kind() { ty::Closure(_, args) => args.as_closure().sig(), _ => bug!(), }; let ty_fn_ptr_from = - Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety)); + Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety)); if let Err(terr) = self.eq_types( *ty, diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 493c41e59e3..cbd8a4125cd 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -546,7 +546,10 @@ impl<'bccx, 'tcx> ObligationEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx self.type_checker.param_env } - fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) { + fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ) { self.register_obligations( obligations .into_iter() diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 064cf7d7f0f..4721e74b955 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -3,7 +3,7 @@ use crate::util::check_builtin_macro_attribute; use rustc_ast::ptr::P; use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind}; -use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe}; +use rustc_ast::{Fn, ItemKind, Safety, Stmt, TyKind}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -78,7 +78,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never)); let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; let decl = cx.fn_decl(params, never); - let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() }; + let header = FnHeader { safety: Safety::Unsafe(span), ..FnHeader::default() }; let sig = FnSig { decl, header, span: span }; let body = Some(cx.block_expr(call)); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 52c1ba1757b..46949f731aa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -788,7 +788,7 @@ impl<'a> TraitDef<'a> { Ident::empty(), attrs, ast::ItemKind::Impl(Box::new(ast::Impl { - unsafety: ast::Unsafe::No, + safety: ast::Safety::Default, polarity: ast::ImplPolarity::Positive, defaultness: ast::Defaultness::Final, constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 307e582d65e..bc2c6def68a 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -263,13 +263,13 @@ pub(crate) mod printf { } impl Num { - fn from_str(s: &str, arg: Option<&str>) -> Self { + fn from_str(s: &str, arg: Option<&str>) -> Option<Self> { if let Some(arg) = arg { - Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{arg:?}`"))) + arg.parse().ok().map(|arg| Num::Arg(arg)) } else if s == "*" { - Num::Next + Some(Num::Next) } else { - Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{s:?}`"))) + s.parse().ok().map(|num| Num::Num(num)) } } @@ -421,7 +421,10 @@ pub(crate) mod printf { state = Prec; parameter = None; flags = ""; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + width = at.slice_between(end).and_then(|num| Num::from_str(num, None)); + if width.is_none() { + return fallback(); + } move_to!(end); } // It's invalid, is what it is. @@ -452,7 +455,10 @@ pub(crate) mod printf { '1'..='9' => { let end = at_next_cp_while(next, char::is_ascii_digit); state = Prec; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + width = at.slice_between(end).and_then(|num| Num::from_str(num, None)); + if width.is_none() { + return fallback(); + } move_to!(end); } _ => { @@ -468,7 +474,7 @@ pub(crate) mod printf { match end.next_cp() { Some(('$', end2)) => { state = Prec; - width = Some(Num::from_str("", Some(at.slice_between(end).unwrap()))); + width = Num::from_str("", at.slice_between(end)); move_to!(end2); } _ => { @@ -500,7 +506,7 @@ pub(crate) mod printf { match end.next_cp() { Some(('$', end2)) => { state = Length; - precision = Some(Num::from_str("*", next.slice_between(end))); + precision = Num::from_str("*", next.slice_between(end)); move_to!(end2); } _ => { @@ -513,7 +519,7 @@ pub(crate) mod printf { '0'..='9' => { let end = at_next_cp_while(next, char::is_ascii_digit); state = Length; - precision = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + precision = at.slice_between(end).and_then(|num| Num::from_str(num, None)); move_to!(end); } _ => return fallback(), diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index a1630ad1379..b44ff979303 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -6,7 +6,7 @@ use rustc_ast::expand::allocator::{ }; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind}; -use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe}; +use rustc_ast::{Fn, ItemKind, Mutability, Safety, Stmt, Ty, TyKind}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -73,7 +73,7 @@ impl AllocFnFactory<'_, '_> { let result = self.call_allocator(method.name, args); let output_ty = self.ret_ty(&method.output); let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty)); - let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() }; + let header = FnHeader { safety: Safety::Unsafe(self.span), ..FnHeader::default() }; let sig = FnSig { decl, header, span: self.span }; let body = Some(self.cx.block_expr(result)); let kind = ItemKind::Fn(Box::new(Fn { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 1e4bf4611cf..8f96070d149 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -549,7 +549,7 @@ fn check_test_signature( let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let dcx = cx.dcx(); - if let ast::Unsafe::Yes(span) = f.sig.header.unsafety { + if let ast::Safety::Unsafe(span) = f.sig.header.safety { return Err(dcx.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index b6d6d211e65..4146137c226 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -872,7 +872,7 @@ pub(crate) fn assert_assignable<'tcx>( let FnSig { inputs_and_output: types_from, c_variadic: c_variadic_from, - unsafety: unsafety_from, + safety: unsafety_from, abi: abi_from, } = from_sig; let to_sig = fx @@ -881,7 +881,7 @@ pub(crate) fn assert_assignable<'tcx>( let FnSig { inputs_and_output: types_to, c_variadic: c_variadic_to, - unsafety: unsafety_to, + safety: unsafety_to, abi: abi_to, } = to_sig; let mut types_from = types_from.iter(); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 451e5258ebd..43f12b514af 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -670,11 +670,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let step3 = self.or(left, right); // Fourth step. - if width == 8 { - step3 - } else { - self.gcc_bswap(step3, width) - } + if width == 8 { step3 } else { self.gcc_bswap(step3, width) } } 128 => { // TODO(antoyo): find a more efficient implementation? @@ -1225,7 +1221,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( iter::once(i8p), tcx.types.unit, false, - rustc_hir::Unsafety::Unsafe, + rustc_hir::Safety::Unsafe, Abi::Rust, )), ); @@ -1236,7 +1232,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( [i8p, i8p].iter().cloned(), tcx.types.unit, false, - rustc_hir::Unsafety::Unsafe, + rustc_hir::Safety::Unsafe, Abi::Rust, )), ); @@ -1245,7 +1241,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( [try_fn_ty, i8p, catch_fn_ty], tcx.types.i32, false, - rustc_hir::Unsafety::Unsafe, + rustc_hir::Safety::Unsafe, Abi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b0b867701a4..c0a1208a8c7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -990,7 +990,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [i8p], tcx.types.unit, false, - hir::Unsafety::Unsafe, + hir::Safety::Unsafe, Abi::Rust, )), ); @@ -1001,7 +1001,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [i8p, i8p], tcx.types.unit, false, - hir::Unsafety::Unsafe, + hir::Safety::Unsafe, Abi::Rust, )), ); @@ -1010,7 +1010,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [try_fn_ty, i8p, catch_fn_ty], tcx.types.i32, false, - hir::Unsafety::Unsafe, + hir::Safety::Unsafe, Abi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index c28b0d644e6..9bf055b1739 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -276,7 +276,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::target_feature => { if !tcx.is_closure_like(did.to_def_id()) && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal + && fn_sig.skip_binder().safety() == hir::Safety::Safe { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index e9c7606dc5a..07473ee476b 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -365,7 +365,7 @@ fn push_debuginfo_type_name<'tcx>( } output.push_str(" (*)("); } else { - output.push_str(sig.unsafety.prefix_str()); + output.push_str(sig.safety.prefix_str()); if sig.abi != rustc_target::spec::abi::Abi::Rust { output.push_str("extern \""); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 936ed41a294..ff176a79675 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -121,7 +121,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.write_operand_repeatedly(cg_elem, count, dest); } - mir::Rvalue::Aggregate(ref kind, ref operands) => { + // This implementation does field projection, so never use it for `RawPtr`, + // which will always be fine with the `codegen_rvalue_operand` path below. + mir::Rvalue::Aggregate(ref kind, ref operands) + if !matches!(**kind, mir::AggregateKind::RawPtr(..)) => + { let (variant_index, variant_dest, active_field_index) = match **kind { mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { let variant_dest = dest.project_downcast(bx, variant_index); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index fdeccb90700..9fd6eb8edab 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -247,7 +247,10 @@ pub trait BuilderMethods<'a, 'tcx>: } else { (in_ty, dest_ty) }; - assert!(matches!(self.cx().type_kind(float_ty), TypeKind::Float | TypeKind::Double)); + assert!(matches!( + self.cx().type_kind(float_ty), + TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128 + )); assert_eq!(self.cx().type_kind(int_ty), TypeKind::Integer); if let Some(false) = self.cx().sess().opts.unstable_opts.saturating_float_casts { diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index ddad6683afb..8c66888d100 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -81,8 +81,8 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if cfg!(debug_assertions) && stab.promotable { let sig = tcx.fn_sig(def_id); assert_eq!( - sig.skip_binder().unsafety(), - hir::Unsafety::Normal, + sig.skip_binder().safety(), + hir::Safety::Safe, "don't mark const unsafe fns as promotable", // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682 ); diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d9add1c9b3b..4bf7dccab92 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -112,6 +112,12 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst } } +impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> { + fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + format!("{self:?}").into_diag_arg() + } +} + into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagArg for bool { diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 7ae988a5be6..530b37aadb1 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -10,6 +10,11 @@ expand_attribute_meta_item = expand_attribute_single_word = attribute must only be a single word +expand_attributes_on_expressions_experimental = + attributes on expressions are experimental + .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//` + .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !` + expand_attributes_wrong_form = attribute must be of form: `attributes(foo, bar)` diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 67a5a9128cc..35f0d8abffc 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -382,7 +382,6 @@ impl<'a> StripUnconfigured<'a> { } /// If attributes are not allowed on expressions, emit an error for `attr` - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if self.features.is_some_and(|features| !features.stmt_expr_attributes) @@ -392,11 +391,15 @@ impl<'a> StripUnconfigured<'a> { &self.sess, sym::stmt_expr_attributes, attr.span, - "attributes on expressions are experimental", + crate::fluent_generated::expand_attributes_on_expressions_experimental, ); if attr.is_doc_comment() { - err.help("`///` is for documentation comments. For a plain comment, use `//`."); + err.help(if attr.style == AttrStyle::Outer { + crate::fluent_generated::expand_help_outer_doc + } else { + crate::fluent_generated::expand_help_inner_doc + }); } err.emit(); diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 3fee39dd085..442fd654b6a 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -55,7 +55,7 @@ pub(super) fn failed_to_match_macro<'cx>( let span = token.span.substitute_dummy(sp); - let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token)); + let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token, None)); err.span_label(span, label); if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); @@ -200,9 +200,17 @@ impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { } /// Currently used by macro_rules! compilation to extract a little information from the `Failure` case. -pub struct FailureForwarder; +pub struct FailureForwarder<'matcher> { + expected_token: Option<&'matcher Token>, +} + +impl<'matcher> FailureForwarder<'matcher> { + pub fn new() -> Self { + Self { expected_token: None } + } +} -impl<'matcher> Tracker<'matcher> for FailureForwarder { +impl<'matcher> Tracker<'matcher> for FailureForwarder<'matcher> { type Failure = (Token, usize, &'static str); fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure { @@ -212,6 +220,14 @@ impl<'matcher> Tracker<'matcher> for FailureForwarder { fn description() -> &'static str { "failure-forwarder" } + + fn set_expected_token(&mut self, tok: &'matcher Token) { + self.expected_token = Some(tok); + } + + fn get_expected_token(&self) -> Option<&'matcher Token> { + self.expected_token + } } pub(super) fn emit_frag_parse_err( @@ -320,9 +336,19 @@ pub(super) fn annotate_doc_comment(dcx: &DiagCtxt, err: &mut Diag<'_>, sm: &Sour /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For /// other tokens, this is "unexpected token...". -pub(super) fn parse_failure_msg(tok: &Token) -> Cow<'static, str> { - match tok.kind { - token::Eof => Cow::from("unexpected end of macro invocation"), - _ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))), +pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> { + if let Some(expected_token) = expected_token { + Cow::from(format!( + "expected `{}`, found `{}`", + pprust::token_to_string(expected_token), + pprust::token_to_string(tok), + )) + } else { + match tok.kind { + token::Eof => Cow::from("unexpected end of macro invocation"), + _ => { + Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))) + } + } } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 27cf6fee702..2fbd09fd9ae 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -541,6 +541,8 @@ impl TtParser { // The separator matches the current token. Advance past it. mp.idx += 1; self.next_mps.push(mp); + } else { + track.set_expected_token(separator); } } &MatcherLoc::SequenceKleeneOpAfterSep { idx_first } => { @@ -632,6 +634,7 @@ impl TtParser { parser.approx_token_stream_pos(), track, ); + if let Some(res) = res { return res; } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 470bde232d7..8f18055f838 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -167,6 +167,11 @@ pub(super) trait Tracker<'matcher> { fn recovery() -> Recovery { Recovery::Forbidden } + + fn set_expected_token(&mut self, _tok: &'matcher Token) {} + fn get_expected_token(&self) -> Option<&'matcher Token> { + None + } } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to @@ -447,16 +452,14 @@ pub fn compile_declarative_macro( // For this we need to reclone the macro body as the previous parser consumed it. let retry_parser = create_parser(); - let parse_result = tt_parser.parse_tt( - &mut Cow::Owned(retry_parser), - &argument_gram, - &mut diagnostics::FailureForwarder, - ); + let mut track = diagnostics::FailureForwarder::new(); + let parse_result = + tt_parser.parse_tt(&mut Cow::Owned(retry_parser), &argument_gram, &mut track); let Failure((token, _, msg)) = parse_result else { unreachable!("matcher returned something other than Failure after retry"); }; - let s = parse_failure_msg(&token); + let s = parse_failure_msg(&token, track.get_expected_token()); let sp = token.span.substitute_dummy(def.span); let mut err = sess.dcx().struct_span_err(sp, s); err.span_label(sp, msg); @@ -1290,7 +1293,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt | NonterminalKind::Expr => { + NonterminalKind::Stmt | NonterminalKind::Expr | NonterminalKind::Expr2021 => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 2e5596f51c3..d3ea48e2e2a 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -16,6 +16,10 @@ use rustc_span::Span; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ `literal`, `path`, `meta`, `tt`, `item` and `vis`"; +const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ + `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \ + `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ + `item` and `vis`"; /// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a @@ -63,35 +67,60 @@ pub(super) fn parse( Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { let span = token.span.with_lo(start_sp.lo()); - + let edition = || { + // FIXME(#85708) - once we properly decode a foreign + // crate's `SyntaxContext::root`, then we can replace + // this with just `span.edition()`. A + // `SyntaxContext::root()` from the current crate will + // have the edition of the current crate, and a + // `SyntaxContext::root()` from a foreign crate will + // have the edition of that crate (which we manually + // retrieve via the `edition` parameter). + if !span.from_expansion() { + edition + } else { + span.edition() + } + }; let kind = - token::NonterminalKind::from_symbol(fragment.name, || { - // FIXME(#85708) - once we properly decode a foreign - // crate's `SyntaxContext::root`, then we can replace - // this with just `span.edition()`. A - // `SyntaxContext::root()` from the current crate will - // have the edition of the current crate, and a - // `SyntaxContext::root()` from a foreign crate will - // have the edition of that crate (which we manually - // retrieve via the `edition` parameter). - if !span.from_expansion() { - edition - } else { - span.edition() - } - }) - .unwrap_or_else( - || { + token::NonterminalKind::from_symbol(fragment.name, edition) + .unwrap_or_else(|| { + let help = match fragment.name { + sym::expr_2021 => { + format!( + "fragment specifier `expr_2021` \ + requires Rust 2021 or later\n\ + {VALID_FRAGMENT_NAMES_MSG}" + ) + } + _ if edition().at_least_rust_2021() + && features + .expr_fragment_specifier_2024 => + { + VALID_FRAGMENT_NAMES_MSG_2021.into() + } + _ => VALID_FRAGMENT_NAMES_MSG.into(), + }; sess.dcx().emit_err( errors::InvalidFragmentSpecifier { span, fragment, - help: VALID_FRAGMENT_NAMES_MSG.into(), + help, }, ); token::NonterminalKind::Ident - }, - ); + }); + if kind == token::NonterminalKind::Expr2021 + && !features.expr_fragment_specifier_2024 + { + rustc_session::parse::feature_err( + sess, + sym::expr_fragment_specifier_2024, + span, + "fragment specifier `expr_2021` is unstable", + ) + .emit(); + } result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); continue; } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 60b386acf91..c6fc9de119d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -458,6 +458,8 @@ declare_features! ( (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), + /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment. + (incomplete, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)), /// Allows using `efiapi`, `sysv64` and `win64` as calling convention /// for functions with varargs. (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6e4cef068c5..2f4dcdbdf2b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2604,7 +2604,7 @@ impl PrimTy { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct BareFnTy<'hir> { - pub unsafety: Unsafety, + pub safety: Safety, pub abi: Abi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, @@ -3172,9 +3172,9 @@ impl<'hir> Item<'hir> { ItemKind::Union(data, gen), (data, gen); expect_trait, - (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), - ItemKind::Trait(is_auto, unsafety, gen, bounds, items), - (*is_auto, *unsafety, gen, bounds, items); + (IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), + ItemKind::Trait(is_auto, safety, gen, bounds, items), + (*is_auto, *safety, gen, bounds, items); expect_trait_alias, (&'hir Generics<'hir>, GenericBounds<'hir>), ItemKind::TraitAlias(gen, bounds), (gen, bounds); @@ -3185,25 +3185,25 @@ impl<'hir> Item<'hir> { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] -pub enum Unsafety { +pub enum Safety { Unsafe, - Normal, + Safe, } -impl Unsafety { - pub fn prefix_str(&self) -> &'static str { +impl Safety { + pub fn prefix_str(self) -> &'static str { match self { Self::Unsafe => "unsafe ", - Self::Normal => "", + Self::Safe => "", } } } -impl fmt::Display for Unsafety { +impl fmt::Display for Safety { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { Self::Unsafe => "unsafe", - Self::Normal => "normal", + Self::Safe => "safe", }) } } @@ -3225,7 +3225,7 @@ impl fmt::Display for Constness { #[derive(Copy, Clone, Debug, HashStable_Generic)] pub struct FnHeader { - pub unsafety: Unsafety, + pub safety: Safety, pub constness: Constness, pub asyncness: IsAsync, pub abi: Abi, @@ -3241,7 +3241,7 @@ impl FnHeader { } pub fn is_unsafe(&self) -> bool { - matches!(&self.unsafety, Unsafety::Unsafe) + matches!(&self.safety, Safety::Unsafe) } } @@ -3284,7 +3284,7 @@ pub enum ItemKind<'hir> { /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`. Union(VariantData<'hir>, &'hir Generics<'hir>), /// A trait definition. - Trait(IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), + Trait(IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), /// A trait alias. TraitAlias(&'hir Generics<'hir>, GenericBounds<'hir>), @@ -3294,7 +3294,7 @@ pub enum ItemKind<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Impl<'hir> { - pub unsafety: Unsafety, + pub safety: Safety, pub polarity: ImplPolarity, pub defaultness: Defaultness, // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 664784cd2c6..b202ea8dca3 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -545,7 +545,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id())); } ItemKind::Impl(Impl { - unsafety: _, + safety: _, defaultness: _, polarity: _, defaultness_span: _, diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 5562b81871f..38ecd7dd082 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -2,7 +2,7 @@ //! [`rustc_middle::ty`] form. use rustc_hir::LangItem; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::Span; /// Collects together a list of type bounds. These lists of bounds occur in many places @@ -34,7 +34,7 @@ impl<'tcx> Bounds<'tcx> { span: Span, ) { self.clauses - .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span)); + .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span)); } pub fn push_trait_bound( @@ -49,7 +49,7 @@ impl<'tcx> Bounds<'tcx> { .map_bound(|trait_ref| { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) }) - .to_predicate(tcx), + .upcast(tcx), span, ); // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. @@ -67,7 +67,7 @@ impl<'tcx> Bounds<'tcx> { span: Span, ) { self.clauses.push(( - projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx), + projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx), span, )); } @@ -76,7 +76,7 @@ impl<'tcx> Bounds<'tcx> { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.clauses.insert(0, (trait_ref.to_predicate(tcx), span)); + self.clauses.insert(0, (trait_ref.upcast(tcx), span)); } pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 39940c8f0f3..44bf8fd2d93 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -14,7 +14,7 @@ use rustc_infer::traits::{util, FulfillmentError}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::ToPredicate; +use rustc_middle::ty::Upcast; use rustc_middle::ty::{ self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -2211,7 +2211,7 @@ fn param_env_with_gat_bounds<'tcx>( }, bound_vars, ) - .to_predicate(tcx), + .upcast(tcx), ), }; } @@ -2250,7 +2250,7 @@ fn try_report_async_mismatch<'tcx>( for error in errors { if let ObligationCauseCode::WhereClause(def_id, _) = *error.root_obligation.cause.code() && def_id == async_future_def_id - && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred() + && let Some(proj) = error.root_obligation.predicate.as_projection_clause() && let Some(proj) = proj.no_bound_vars() && infcx.can_eq( error.root_obligation.param_env, diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index e44e8e67da3..25ac31c16c7 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -156,7 +156,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { [], expected_return_type, false, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::Rust, )); @@ -252,7 +252,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], tcx.types.isize, false, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::Rust, )); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 00ff470a0a7..d829e720d9e 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -71,13 +71,13 @@ fn equate_intrinsic_type<'tcx>( } /// Returns the unsafety of the given intrinsic. -pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Unsafety { +pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { - tcx.fn_sig(intrinsic_id).skip_binder().unsafety() + tcx.fn_sig(intrinsic_id).skip_binder().safety() } else { match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { - true => hir::Unsafety::Normal, - false => hir::Unsafety::Unsafe, + true => hir::Safety::Safe, + false => hir::Safety::Unsafe, } }; let is_in_list = match tcx.item_name(intrinsic_id.into()) { @@ -136,8 +136,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::fmul_algebraic | sym::fdiv_algebraic | sym::frem_algebraic - | sym::const_eval_select => hir::Unsafety::Normal, - _ => hir::Unsafety::Unsafe, + | sym::const_eval_select => hir::Safety::Safe, + _ => hir::Safety::Unsafe, }; if has_safe_attr != is_in_list { @@ -197,7 +197,7 @@ pub fn check_intrinsic_type( }) }; - let (n_tps, n_lts, n_cts, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let (n_tps, n_lts, n_cts, inputs, output, safety) = if name_str.starts_with("atomic_") { let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -219,9 +219,9 @@ pub fn check_intrinsic_type( return; } }; - (n_tps, 0, 0, inputs, output, hir::Unsafety::Unsafe) + (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe) } else { - let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id); + let safety = intrinsic_operation_unsafety(tcx, intrinsic_id); let (n_tps, n_cts, inputs, output) = match intrinsic_name { sym::abort => (0, 0, vec![], tcx.types.never), sym::unreachable => (0, 0, vec![], tcx.types.never), @@ -514,14 +514,14 @@ pub fn check_intrinsic_type( [mut_u8], tcx.types.unit, false, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::Rust, )); let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8, mut_u8], tcx.types.unit, false, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::Rust, )); ( @@ -656,9 +656,9 @@ pub fn check_intrinsic_type( return; } }; - (n_tps, 0, n_cts, inputs, output, unsafety) + (n_tps, 0, n_cts, inputs, output, safety) }; - let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, abi); + let sig = tcx.mk_fn_sig(inputs, output, false, safety, abi); let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig) } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index f8b0164b9a5..0083da2a1e4 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -456,7 +456,7 @@ fn fn_sig_suggestion<'tcx>( let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() }; - let unsafety = sig.unsafety.prefix_str(); + let safety = sig.safety.prefix_str(); let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates); // FIXME: this is not entirely correct, as the lifetimes from borrowed params will @@ -464,9 +464,7 @@ fn fn_sig_suggestion<'tcx>( // lifetimes between the `impl` and the `trait`, but this should be good enough to // fill in a significant portion of the missing code, and other subsequent // suggestions can help the user fix the code. - format!( - "{unsafety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}" - ) + format!("{safety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}") } /// Return placeholder code for the given associated item. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b918a8c32d8..e137aab2109 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -20,8 +20,8 @@ use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_middle::ty::{GenericArgKind, GenericArgs}; use rustc_middle::{bug, span_bug}; @@ -685,7 +685,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // `Self: 'me`.) bounds.insert( ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param)) - .to_predicate(tcx), + .upcast(tcx), ); } } @@ -730,7 +730,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( region_a_param, region_b_param, )) - .to_predicate(tcx), + .upcast(tcx), ); } } @@ -1350,12 +1350,12 @@ fn check_impl<'tcx>( // We already have a better span. continue; } - if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() + if let Some(pred) = obligation.predicate.as_trait_clause() && pred.skip_binder().self_ty() == trait_ref.self_ty() { obligation.cause.span = hir_self_ty.span; } - if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + if let Some(pred) = obligation.predicate.as_projection_clause() && pred.skip_binder().self_ty() == trait_ref.self_ty() { obligation.cause.span = hir_self_ty.span; diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 28735429210..5fe21e9b822 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -2,7 +2,7 @@ //! crate or pertains to a type defined in this crate. use rustc_errors::{codes::*, struct_span_code_err}; -use rustc_hir::Unsafety; +use rustc_hir::Safety; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TraitDef, TyCtxt}; use rustc_span::def_id::LocalDefId; @@ -18,8 +18,8 @@ pub(super) fn check_item( tcx.generics_of(def_id).own_params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); let trait_ref = trait_header.trait_ref.instantiate_identity(); - match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { - (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { + match (trait_def.safety, unsafe_attr, trait_header.safety, trait_header.polarity) { + (Safety::Safe, None, Safety::Unsafe, Positive | Reservation) => { let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), @@ -37,7 +37,7 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Unsafe, _, Unsafety::Normal, Positive | Reservation) => { + (Safety::Unsafe, _, Safety::Safe, Positive | Reservation) => { let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), @@ -61,7 +61,7 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Normal, Some(attr_name), Unsafety::Normal, Positive | Reservation) => { + (Safety::Safe, Some(attr_name), Safety::Safe, Positive | Reservation) => { let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), @@ -85,14 +85,14 @@ pub(super) fn check_item( .emit()); } - (_, _, Unsafety::Unsafe, Negative) => { + (_, _, Safety::Unsafe, Negative) => { // Reported in AST validation assert!(tcx.dcx().has_errors().is_some(), "unsafe negative impl"); Ok(()) } - (_, _, Unsafety::Normal, Negative) - | (Unsafety::Unsafe, _, Unsafety::Unsafe, Positive | Reservation) - | (Unsafety::Normal, Some(_), Unsafety::Unsafe, Positive | Reservation) - | (Unsafety::Normal, None, Unsafety::Normal, _) => Ok(()), + (_, _, Safety::Safe, Negative) + | (Safety::Unsafe, _, Safety::Unsafe, Positive | Reservation) + | (Safety::Safe, Some(_), Safety::Unsafe, Positive | Reservation) + | (Safety::Safe, None, Safety::Safe, _) => Ok(()), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 0b9f7fd41fb..aa28b2c8e2c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -29,7 +29,7 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -1102,11 +1102,11 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let item = tcx.hir().expect_item(def_id); - let (is_auto, unsafety, items) = match item.kind { - hir::ItemKind::Trait(is_auto, unsafety, .., items) => { - (is_auto == hir::IsAuto::Yes, unsafety, items) + let (is_auto, safety, items) = match item.kind { + hir::ItemKind::Trait(is_auto, safety, .., items) => { + (is_auto == hir::IsAuto::Yes, safety, items) } - hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal, &[][..]), + hir::ItemKind::TraitAlias(..) => (false, hir::Safety::Safe, &[][..]), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; @@ -1247,7 +1247,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { ty::TraitDef { def_id: def_id.to_def_id(), - unsafety, + safety, paren_sugar, has_auto_impl: is_auto, is_marker, @@ -1286,7 +1286,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig< { icx.lowerer().lower_fn_ty( hir_id, - sig.header.unsafety, + sig.header.safety, sig.header.abi, sig.decl, Some(generics), @@ -1301,14 +1301,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig< kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _), generics, .. - }) => icx.lowerer().lower_fn_ty( - hir_id, - header.unsafety, - header.abi, - decl, - Some(generics), - None, - ), + }) => { + icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None) + } ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); @@ -1321,8 +1316,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig< let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity()); // constructors for structs with `layout_scalar_valid_range` are unsafe to call let safety = match tcx.layout_scalar_valid_range(adt_def_id) { - (Bound::Unbounded, Bound::Unbounded) => hir::Unsafety::Normal, - _ => hir::Unsafety::Unsafe, + (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe, + _ => hir::Safety::Unsafe, }; ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, abi::Abi::Rust)) } @@ -1409,13 +1404,13 @@ fn infer_return_ty_for_fn_sig<'tcx>( fn_sig.inputs().iter().copied(), recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)), fn_sig.c_variadic, - fn_sig.unsafety, + fn_sig.safety, fn_sig.abi, )) } None => icx.lowerer().lower_fn_ty( hir_id, - sig.header.unsafety, + sig.header.safety, sig.header.abi, sig.decl, Some(generics), @@ -1574,7 +1569,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai }; ty::ImplTraitHeader { trait_ref: ty::EarlyBinder::bind(trait_ref), - unsafety: impl_.unsafety, + safety: impl_.safety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) } }) @@ -1665,7 +1660,7 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate def_id, inferred_outlives, ); let inferred_outlives_iter = - inferred_outlives.iter().map(|(clause, span)| ((*clause).to_predicate(tcx), *span)); + inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span)); if result.predicates.is_empty() { result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); } else { @@ -1685,14 +1680,14 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( decl: &'tcx hir::FnDecl<'tcx>, abi: abi::Abi, ) -> ty::PolyFnSig<'tcx> { - let unsafety = if abi == abi::Abi::RustIntrinsic { + let safety = if abi == abi::Abi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id) } else { - hir::Unsafety::Unsafe + hir::Safety::Unsafe }; let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = - ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, unsafety, abi, decl, None, None); + ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index d348d6f789f..db36aba7edf 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -9,7 +9,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate}; +use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -40,11 +40,13 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // `tcx.def_span(def_id);` let span = DUMMY_SP; - result.predicates = - tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), - span, - )))); + result.predicates = tcx.arena.alloc_from_iter( + result + .predicates + .iter() + .copied() + .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))), + ); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result @@ -165,7 +167,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); + predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id))); } // Collect the predicates that were written inline by the user on each @@ -196,10 +198,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen .no_bound_vars() .expect("const parameters cannot be generic"); let ct = icx.lowerer().lower_const_param(param.hir_id, ct_ty); - predicates.insert(( - ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), - param.span, - )); + predicates + .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span)); } } } @@ -228,7 +228,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ty::ClauseKind::WellFormed(ty.into()), bound_vars, ); - predicates.insert((predicate.to_predicate(tcx), span)); + predicates.insert((predicate.upcast(tcx), span)); } } @@ -257,8 +257,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ) } }; - let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) - .to_predicate(tcx); + let pred = + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx); (pred, span) })) } @@ -328,12 +328,12 @@ fn compute_bidirectional_outlives_predicates<'tcx>( let span = tcx.def_span(param.def_id); predicates.push(( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime)) - .to_predicate(tcx), + .upcast(tcx), span, )); predicates.push(( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime)) - .to_predicate(tcx), + .upcast(tcx), span, )); } @@ -354,8 +354,7 @@ fn const_evaluatable_predicates_of( let ct = ty::Const::from_anon_const(self.tcx, c.def_id); if let ty::ConstKind::Unevaluated(_) = ct.kind() { let span = self.tcx.def_span(c.def_id); - self.preds - .insert((ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span)); + self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span)); } } @@ -694,7 +693,7 @@ pub(super) fn type_param_predicates( && param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id()); - extend = Some((identity_trait_ref.to_predicate(tcx), item.span)); + extend = Some((identity_trait_ref.upcast(tcx), item.span)); } let icx = ItemCtxt::new(tcx, item_def_id); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index d16648b9e8f..39016d15236 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2080,14 +2080,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_fn_ptr( tcx, - self.lower_fn_ty( - hir_ty.hir_id, - bf.unsafety, - bf.abi, - bf.decl, - None, - Some(hir_ty), - ), + self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)), ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { @@ -2309,11 +2302,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Lower a function type from the HIR to our internal notion of a function signature. - #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)] + #[instrument(level = "debug", skip(self, hir_id, safety, abi, decl, generics, hir_ty), ret)] pub fn lower_fn_ty( &self, hir_id: HirId, - unsafety: hir::Unsafety, + safety: hir::Safety, abi: abi::Abi, decl: &hir::FnDecl<'tcx>, generics: Option<&hir::Generics<'_>>, @@ -2376,7 +2369,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?output_ty); - let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); + let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); if !self.allow_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 30b99a095f3..4f7a39d0250 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -9,7 +9,7 @@ use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::span_bug; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable}; -use rustc_middle::ty::{DynKind, ToPredicate}; +use rustc_middle::ty::{DynKind, Upcast}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations}; @@ -119,7 +119,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); for (base_trait_ref, span) in regular_traits_refs_spans { - let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); + let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx); for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { debug!("observing object predicate `{pred:?}`"); diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index a87112dcc12..97fd7731b1e 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgKind; -use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt}; +use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt, Upcast}; use rustc_span::Span; mod explicit; @@ -75,14 +75,14 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { match kind1.unpack() { GenericArgKind::Type(ty1) => Some(( ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)) - .to_predicate(tcx), + .upcast(tcx), span, )), GenericArgKind::Lifetime(region1) => Some(( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( region1, *region2, )) - .to_predicate(tcx), + .upcast(tcx), span, )), GenericArgKind::Const(_) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a47e6af0bf2..29c7e576d2b 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -287,7 +287,7 @@ impl<'a> State<'a> { self.pclose(); } hir::TyKind::BareFn(f) => { - self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); + self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), @@ -351,7 +351,7 @@ impl<'a> State<'a> { self.print_fn( decl, hir::FnHeader { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, constness: hir::Constness::NotConst, abi: Abi::Rust, asyncness: hir::IsAsync::NotAsync, @@ -582,7 +582,7 @@ impl<'a> State<'a> { self.print_struct(struct_def, generics, item.ident.name, item.span, true); } hir::ItemKind::Impl(&hir::Impl { - unsafety, + safety, polarity, defaultness, defaultness_span: _, @@ -593,7 +593,7 @@ impl<'a> State<'a> { }) => { self.head(""); self.print_defaultness(defaultness); - self.print_unsafety(unsafety); + self.print_safety(safety); self.word_nbsp("impl"); if !generics.params.is_empty() { @@ -622,10 +622,10 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => { + hir::ItemKind::Trait(is_auto, safety, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); - self.print_unsafety(unsafety); + self.print_safety(safety); self.word_nbsp("trait"); self.print_ident(item.ident); self.print_generic_params(generics.params); @@ -2234,7 +2234,7 @@ impl<'a> State<'a> { fn print_ty_fn( &mut self, abi: Abi, - unsafety: hir::Unsafety, + safety: hir::Safety, decl: &hir::FnDecl<'_>, name: Option<Symbol>, generic_params: &[hir::GenericParam<'_>], @@ -2246,7 +2246,7 @@ impl<'a> State<'a> { self.print_fn( decl, hir::FnHeader { - unsafety, + safety, abi, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, @@ -2267,7 +2267,7 @@ impl<'a> State<'a> { hir::IsAsync::Async(_) => self.word_nbsp("async"), } - self.print_unsafety(header.unsafety); + self.print_safety(header.safety); if header.abi != Abi::Rust { self.word_nbsp("extern"); @@ -2284,10 +2284,10 @@ impl<'a> State<'a> { } } - fn print_unsafety(&mut self, s: hir::Unsafety) { + fn print_safety(&mut self, s: hir::Safety) { match s { - hir::Unsafety::Normal => {} - hir::Unsafety::Unsafe => self.word_nbsp("unsafe"), + hir::Safety::Safe => {} + hir::Safety::Unsafe => self.word_nbsp("unsafe"), } } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 502a176845e..9736c8b8920 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tupled_upvars_ty, ), coroutine_closure_sig.c_variadic, - coroutine_closure_sig.unsafety, + coroutine_closure_sig.safety, coroutine_closure_sig.abi, ); let adjustments = self.adjust_steps(autoderef); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 89e64cf5f0d..843d9e38714 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -216,7 +216,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> ty::BoundVariableKind::Region(ty::BrAnon), ]); let expected_sig = ty::Binder::bind_with_vars( - tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.unsafety, Abi::Rust), + tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.safety, Abi::Rust), bounds, ); @@ -239,7 +239,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name); let main_fn_ty = Ty::new_fn_ptr( tcx, - Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust)), + Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Safety::Safe, Abi::Rust)), ); let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( @@ -251,7 +251,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: ], tcx.types.isize, false, - fn_sig.unsafety, + fn_sig.safety, Abi::Rust, )); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index aca069d8fb5..14a6177141c 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [Ty::new_tup(tcx, sig.inputs())], sig.output(), sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ) }); @@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ], Ty::new_tup(tcx, &[bound_yield_ty, bound_return_ty]), sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ) }), @@ -281,7 +281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { liberated_sig.inputs().iter().copied(), coroutine_output_ty, liberated_sig.c_variadic, - liberated_sig.unsafety, + liberated_sig.safety, liberated_sig.abi, ); @@ -493,7 +493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { input_tys, ret_param_ty, false, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::Rust, )); @@ -605,7 +605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sig.inputs().iter().cloned(), sig.output(), sig.c_variadic, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::RustCall, ) }); @@ -743,7 +743,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inputs, supplied_output_ty, expected_sigs.liberated_sig.c_variadic, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::RustCall, ); @@ -820,7 +820,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_arguments, supplied_return, decl.c_variadic, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::RustCall, ), bound_vars, @@ -984,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_arguments, err_ty, decl.c_variadic, - hir::Unsafety::Normal, + hir::Safety::Safe, Abi::RustCall, )); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 8d93f402f10..d81dab2222a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -788,8 +788,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let outer_universe = self.infcx.universe(); let result = if let ty::FnPtr(fn_ty_b) = b.kind() - && let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) = - (fn_ty_a.unsafety(), fn_ty_b.unsafety()) + && let (hir::Safety::Safe, hir::Safety::Unsafe) = + (fn_ty_a.safety(), fn_ty_b.safety()) { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); self.unify_and(unsafe_a, b, to_unsafe) @@ -851,7 +851,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). - if b_sig.unsafety() == hir::Unsafety::Normal + if b_sig.safety() == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() { return Err(TypeError::TargetFeatureCast(def_id)); @@ -922,14 +922,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // or // `unsafe fn(arg0,arg1,...) -> _` let closure_sig = args_a.as_closure().sig(); - let unsafety = fn_ty.unsafety(); + let safety = fn_ty.safety(); let pointer_ty = - Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, unsafety)); + Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, safety)); debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty); self.unify_and( pointer_ty, b, - simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(unsafety))), + simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))), ) } _ => self.unify_and(a, b, identity), @@ -1126,27 +1126,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::Closure(_, args), ty::FnDef(..)) => { let b_sig = new_ty.fn_sig(self.tcx); let a_sig = - self.tcx.signature_unclosure(args.as_closure().sig(), b_sig.unsafety()); + self.tcx.signature_unclosure(args.as_closure().sig(), b_sig.safety()); (Some(a_sig), Some(b_sig)) } (ty::FnDef(..), ty::Closure(_, args)) => { let a_sig = prev_ty.fn_sig(self.tcx); let b_sig = - self.tcx.signature_unclosure(args.as_closure().sig(), a_sig.unsafety()); + self.tcx.signature_unclosure(args.as_closure().sig(), a_sig.safety()); (Some(a_sig), Some(b_sig)) } - (ty::Closure(_, args_a), ty::Closure(_, args_b)) => { - ( - Some(self.tcx.signature_unclosure( - args_a.as_closure().sig(), - hir::Unsafety::Normal, - )), - Some(self.tcx.signature_unclosure( - args_b.as_closure().sig(), - hir::Unsafety::Normal, - )), - ) - } + (ty::Closure(_, args_a), ty::Closure(_, args_b)) => ( + Some( + self.tcx + .signature_unclosure(args_a.as_closure().sig(), hir::Safety::Safe), + ), + Some( + self.tcx + .signature_unclosure(args_b.as_closure().sig(), hir::Safety::Safe), + ), + ), _ => (None, None), } } @@ -1168,14 +1166,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fn_ptr = Ty::new_fn_ptr(self.tcx, sig); let prev_adjustment = match prev_ty.kind() { ty::Closure(..) => { - Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.unsafety())) + Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.safety())) } ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer), _ => span_bug!(cause.span, "should not try to coerce a {prev_ty} to a fn pointer"), }; let next_adjustment = match new_ty.kind() { ty::Closure(..) => { - Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.unsafety())) + Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.safety())) } ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer), _ => span_bug!(new.span, "should not try to coerce a {new_ty} to a fn pointer"), diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index c79b6be6560..e456bd7fd4a 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -558,7 +558,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( if let Some(def_id) = typeck_results.type_dependent_def_id(ex.hir_id) && let method_ty = self.root_ctxt.tcx.type_of(def_id).instantiate_identity() && let sig = method_ty.fn_sig(self.root_ctxt.tcx) - && let hir::Unsafety::Unsafe = sig.unsafety() + && let hir::Safety::Unsafe = sig.safety() { let mut collector = InferVarCollector { value: (ex.hir_id, ex.span, UnsafeUseReason::Method), @@ -578,7 +578,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( if func_ty.is_fn() && let sig = func_ty.fn_sig(self.root_ctxt.tcx) - && let hir::Unsafety::Unsafe = sig.unsafety() + && let hir::Safety::Unsafe = sig.safety() { let mut collector = InferVarCollector { value: (ex.hir_id, ex.span, UnsafeUseReason::Call), @@ -609,7 +609,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( // `is_fn` excludes closures, but those can't be unsafe. if ty.is_fn() && let sig = ty.fn_sig(self.root_ctxt.tcx) - && let hir::Unsafety::Unsafe = sig.unsafety() + && let hir::Safety::Unsafe = sig.safety() { let mut collector = InferVarCollector { value: (ex.hir_id, ex.span, UnsafeUseReason::Path), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index ac1e26df870..23f4d3c36a3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,7 +1,7 @@ //! A utility module to inspect currently ambiguous obligations in the current context. use crate::FnCtxt; -use rustc_infer::traits::solve::Goal; use rustc_infer::traits::{self, ObligationCause}; +use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::solve::inspect::ProofTreeInferCtxtExt; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index fe0dd4e393f..56e13cd679d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -28,8 +28,8 @@ use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, suggest_constraining_type_params, Article, Binder, IsSuggestable, ToPredicate, Ty, - TypeVisitableExt, + self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt, + Upcast, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -1716,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]); + self.suggest_derive(diag, &[(trait_ref.upcast(self.tcx), None, None)]); } } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6892da7a5e2..b9a99fbec3c 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -145,7 +145,7 @@ fn typeck_with_fallback<'tcx>( if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { let fn_sig = if decl.output.get_infer_ret_ty().is_some() { - fcx.lowerer().lower_fn_ty(id, header.unsafety, header.abi, decl, None, None) + fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None) } else { tcx.fn_sig(def_id).instantiate_identity() }; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6cfdacf6a24..fc652490a40 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -21,7 +21,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::ToPredicate; +use rustc_middle::ty::Upcast; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; @@ -1496,7 +1496,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx)); + trait_predicate = Some(trait_ref.upcast(self.tcx)); } ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { let trait_ref = self.instantiate_binder_with_fresh_vars( diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index e371775be0a..87b76b978b9 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -583,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !errors.is_empty() { for error in errors { if let Some(trait_pred) = - error.obligation.predicate.to_opt_poly_trait_pred() + error.obligation.predicate.as_trait_clause() { let output_associated_item = match error.obligation.cause.code() { @@ -797,9 +797,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if operand_ty.has_non_region_param() { - let predicates = errors.iter().filter_map(|error| { - error.obligation.predicate.to_opt_poly_trait_pred() - }); + let predicates = errors + .iter() + .filter_map(|error| error.obligation.predicate.as_trait_clause()); for pred in predicates { self.err_ctxt().suggest_restricting_param_bound( &mut err, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index d313c0eafe1..9d16f0d4815 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -419,7 +419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [], tupled_upvars_ty_for_borrow, false, - hir::Unsafety::Normal, + hir::Safety::Safe, rustc_target::spec::abi::Abi::Rust, ), self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region( diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index eaef715fe5d..16057b6ad9d 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -385,19 +385,31 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { a: Self, b: Self, ) -> TypeTrace<'tcx> { - use GenericArgKind::*; TypeTrace { cause: cause.clone(), values: match (a.unpack(), b.unpack()) { - (Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)), - (Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), - (Const(a), Const(b)) => { + (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => { + Regions(ExpectedFound::new(a_is_expected, a, b)) + } + (GenericArgKind::Type(a), GenericArgKind::Type(b)) => { + Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) + } + (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) } - (Lifetime(_), Type(_) | Const(_)) - | (Type(_), Lifetime(_) | Const(_)) - | (Const(_), Lifetime(_) | Type(_)) => { + ( + GenericArgKind::Lifetime(_), + GenericArgKind::Type(_) | GenericArgKind::Const(_), + ) + | ( + GenericArgKind::Type(_), + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_), + ) + | ( + GenericArgKind::Const(_), + GenericArgKind::Lifetime(_) | GenericArgKind::Type(_), + ) => { bug!("relating different kinds: {a:?} {b:?}") } }, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d0687dfc6fd..46a7e7b2399 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -73,7 +73,7 @@ use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; -use rustc_middle::ty::ToPredicate; +use rustc_middle::ty::Upcast; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -516,7 +516,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::CannotNormalize(clause, origin) => { let clause: ty::Clause<'tcx> = - clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx); + clause.map_bound(ty::ClauseKind::TypeOutlives).upcast(self.tcx); self.tcx .dcx() .struct_span_err(origin.span(), format!("cannot normalize `{clause}`")) @@ -1053,8 +1053,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^ - values.0.push(sig1.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety); - values.1.push(sig2.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety); + values.0.push(sig1.safety.prefix_str(), sig1.safety != sig2.safety); + values.1.push(sig2.safety.prefix_str(), sig1.safety != sig2.safety); // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^^^^^ @@ -1928,7 +1928,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.tcx .signature_unclosure( args.as_closure().sig(), - rustc_hir::Unsafety::Normal, + rustc_hir::Safety::Safe, ) .to_string(), ), diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index b4decbf14a2..98fd7906e70 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -168,7 +168,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> { let closure_sig = args.as_closure().sig(); Ty::new_fn_ptr( self.tcx, - self.tcx.signature_unclosure(closure_sig, hir::Unsafety::Normal), + self.tcx.signature_unclosure(closure_sig, hir::Safety::Safe), ) } _ => ty.super_fold_with(self), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 8859772848f..e125f1858dd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -409,10 +409,8 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { { let closure_sig = self_ty.map(|closure| { if let ty::Closure(_, args) = closure.kind() { - self.tcx().signature_unclosure( - args.as_closure().sig(), - rustc_hir::Unsafety::Normal, - ) + self.tcx() + .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe) } else { bug!("type is not longer closure"); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index c24ad1fa1e7..f2fe43380b8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -452,7 +452,7 @@ impl<T> Trait<T> for X { } (ty::FnPtr(sig), ty::FnDef(def_id, _)) | (ty::FnDef(def_id, _), ty::FnPtr(sig)) => { - if tcx.fn_sig(def_id).skip_binder().unsafety() < sig.unsafety() { + if tcx.fn_sig(def_id).skip_binder().safety() < sig.safety() { diag.note( "unsafe functions cannot be coerced into safe function pointers", ); diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index c1baadfa8df..101598c5951 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -29,7 +29,7 @@ use rustc_middle::infer::canonical::OriginalQueryValues; use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; -use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::Span; @@ -337,7 +337,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.obligations.extend(obligations); } - pub fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>) { + pub fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ) { self.obligations.extend(obligations.into_iter().map(|to_pred| { Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred) })) @@ -360,7 +363,10 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { /// Register predicates that must hold in order for this relation to hold. Uses /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should /// be used if control over the obligation causes is required. - fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>); + fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ); /// Register `AliasRelate` obligation(s) that both types must be related to each other. fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>); diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs index b86d1b2671d..a224a86492a 100644 --- a/compiler/rustc_infer/src/infer/relate/glb.rs +++ b/compiler/rustc_infer/src/infer/relate/glb.rs @@ -140,7 +140,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> { self.fields.param_env } - fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) { + fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ) { self.fields.register_predicates(obligations); } diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs index 20f5f65c984..83ab7770770 100644 --- a/compiler/rustc_infer/src/infer/relate/lub.rs +++ b/compiler/rustc_infer/src/infer/relate/lub.rs @@ -140,7 +140,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> { self.fields.param_env } - fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) { + fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ) { self.fields.register_predicates(obligations); } diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 86a24eef7f5..21064fff97f 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -312,7 +312,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { self.structurally_relate_aliases } - fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) { + fn register_predicates( + &mut self, + obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, + ) { self.fields.register_predicates(obligations); } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index cb067c7a660..e27e6a0a4a1 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -2,7 +2,7 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_hir::def_id::DefId; use rustc_macros::extension; -use rustc_middle::ty::{self, ToPredicate, Ty}; +use rustc_middle::ty::{self, Ty, Upcast}; use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; @@ -26,7 +26,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).to_predicate(infcx.tcx), + predicate: trait_ref.upcast(infcx.tcx), }, ); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index f77a92bf9bc..0ae4340098b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -16,7 +16,7 @@ use rustc_hir as hir; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::Certainty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, Ty, TyCtxt, Upcast}; use rustc_span::Span; pub use self::ImplSource::*; @@ -155,7 +155,7 @@ impl<'tcx, O> Obligation<'tcx, O> { tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - predicate: impl ToPredicate<'tcx, O>, + predicate: impl Upcast<TyCtxt<'tcx>, O>, ) -> Obligation<'tcx, O> { Self::with_depth(tcx, cause, 0, param_env, predicate) } @@ -173,9 +173,9 @@ impl<'tcx, O> Obligation<'tcx, O> { cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - predicate: impl ToPredicate<'tcx, O>, + predicate: impl Upcast<TyCtxt<'tcx>, O>, ) -> Obligation<'tcx, O> { - let predicate = predicate.to_predicate(tcx); + let predicate = predicate.upcast(tcx); Obligation { cause, param_env, recursion_depth, predicate } } @@ -184,7 +184,7 @@ impl<'tcx, O> Obligation<'tcx, O> { span: Span, body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, - trait_ref: impl ToPredicate<'tcx, O>, + trait_ref: impl Upcast<TyCtxt<'tcx>, O>, ) -> Obligation<'tcx, O> { Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref) } @@ -192,7 +192,7 @@ impl<'tcx, O> Obligation<'tcx, O> { pub fn with<P>( &self, tcx: TyCtxt<'tcx>, - value: impl ToPredicate<'tcx, P>, + value: impl Upcast<TyCtxt<'tcx>, P>, ) -> Obligation<'tcx, P> { Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value) } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index d8d84b777e0..cc12a4bf091 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation}; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -357,9 +357,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { None } }) - .map(|clause| { - elaboratable.child(bound_clause.rebind(clause).to_predicate(tcx)) - }), + .map(|clause| elaboratable.child(bound_clause.rebind(clause).upcast(tcx))), ); } ty::ClauseKind::RegionOutlives(..) => { @@ -409,14 +407,14 @@ pub fn supertraits<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> { - elaborate(tcx, [trait_ref.to_predicate(tcx)]).filter_only_self().filter_to_traits() + elaborate(tcx, [trait_ref.upcast(tcx)]).filter_only_self().filter_to_traits() } pub fn transitive_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, ) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> { - elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx))) + elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx))) .filter_only_self() .filter_to_traits() } @@ -431,7 +429,7 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>( trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, assoc_name: Ident, ) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> { - elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx))) + elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx))) .filter_only_self_that_defines(assoc_name) .filter_to_traits() } @@ -457,7 +455,7 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits< fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { while let Some(pred) = self.base_iterator.next() { - if let Some(data) = pred.to_opt_poly_trait_pred() { + if let Some(data) = pred.as_trait_clause() { return Some(data.map_bound(|t| t.trait_ref)); } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b9be92b89af..6b9f9d1531e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -57,8 +57,8 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::GenericArgKind; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeVisitableExt; +use rustc_middle::ty::Upcast; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; @@ -360,11 +360,11 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { - ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => { + ast::ItemKind::Trait(box ast::Trait { safety: ast::Safety::Unsafe(_), .. }) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeTrait); } - ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => { + ast::ItemKind::Impl(box ast::Impl { safety: ast::Safety::Unsafe(_), .. }) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl); } @@ -419,7 +419,7 @@ impl EarlyLintPass for UnsafeCode { if let FnKind::Fn( ctxt, _, - ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. }, + ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. }, _, _, body, @@ -734,7 +734,7 @@ fn type_implements_negative_copy_modulo_regions<'tcx>( cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(pred).to_predicate(tcx), + predicate: pred.upcast(tcx), }; tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation) diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 48e5683fc0a..2c86964feef 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -345,8 +345,8 @@ fn structurally_same_type_impl<'tcx>( let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig); let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig); - (a_sig.abi, a_sig.unsafety, a_sig.c_variadic) - == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic) + (a_sig.abi, a_sig.safety, a_sig.c_variadic) + == (b_sig.abi, b_sig.safety, b_sig.c_variadic) && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| { structurally_same_type_impl(seen_types, tcx, param_env, *a, *b, ckind) }) diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index d1cdabc293d..ab0c598ea0c 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -28,6 +28,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } +rustc_next_trait_solver = { path = "../rustc_next_trait_solver" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 13719268737..7392eb6c2bb 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -61,7 +61,7 @@ macro_rules! arena_types { [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] canonical_goal_evaluation: rustc_middle::traits::solve::inspect::GoalEvaluationStep<'tcx>, + [] canonical_goal_evaluation: rustc_next_trait_solver::solve::inspect::GoalEvaluationStep<rustc_middle::ty::TyCtxt<'tcx>>, [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index aee97d77222..49bf03e9c75 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,23 +23,20 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_type_ir::Canonical as IrCanonical; -use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; +pub use rustc_type_ir as ir; pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind}; use smallvec::SmallVec; use std::collections::hash_map::Entry; -use std::ops::Index; use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; use crate::ty::GenericArg; -use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; - -pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>; - -pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo<TyCtxt<'tcx>>; +use crate::ty::{self, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; +pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>; +pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>; +pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>; pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>; impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> { @@ -51,74 +48,6 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> { } } -/// A set of values corresponding to the canonical variables from some -/// `Canonical`. You can give these values to -/// `canonical_value.instantiate` to instantiate them into the canonical -/// value at the right places. -/// -/// When you canonicalize a value `V`, you get back one of these -/// vectors with the original values that were replaced by canonical -/// variables. You will need to supply it later to instantiate the -/// canonicalized query response. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable)] -pub struct CanonicalVarValues<'tcx> { - pub var_values: ty::GenericArgsRef<'tcx>, -} - -impl CanonicalVarValues<'_> { - pub fn is_identity(&self) -> bool { - self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { - ty::GenericArgKind::Lifetime(r) => { - matches!(*r, ty::ReBound(ty::INNERMOST, br) if br.var.as_usize() == bv) - } - ty::GenericArgKind::Type(ty) => { - matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) - } - ty::GenericArgKind::Const(ct) => { - matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) - } - }) - } - - pub fn is_identity_modulo_regions(&self) -> bool { - let mut var = ty::BoundVar::ZERO; - for arg in self.var_values { - match arg.unpack() { - ty::GenericArgKind::Lifetime(r) => { - if let ty::ReBound(ty::INNERMOST, br) = *r - && var == br.var - { - var = var + 1; - } else { - // It's ok if this region var isn't unique - } - } - ty::GenericArgKind::Type(ty) => { - if let ty::Bound(ty::INNERMOST, bt) = *ty.kind() - && var == bt.var - { - var = var + 1; - } else { - return false; - } - } - ty::GenericArgKind::Const(ct) => { - if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind() - && var == bc - { - var = var + 1; - } else { - return false; - } - } - } - } - - true - } -} - /// When we canonicalize a value to form a query, we wind up replacing /// various parts of it with canonical variables. This struct stores /// those replaced bits to remember for when we process the query @@ -218,78 +147,6 @@ TrivialTypeTraversalImpls! { crate::infer::canonical::Certainty, } -impl<'tcx> CanonicalVarValues<'tcx> { - // Given a list of canonical variables, construct a set of values which are - // the identity response. - pub fn make_identity( - tcx: TyCtxt<'tcx>, - infos: CanonicalVarInfos<'tcx>, - ) -> CanonicalVarValues<'tcx> { - CanonicalVarValues { - var_values: tcx.mk_args_from_iter(infos.iter().enumerate().map( - |(i, info)| -> ty::GenericArg<'tcx> { - match info.kind { - CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { - Ty::new_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i).into()) - .into() - } - CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(i), - kind: ty::BrAnon, - }; - ty::Region::new_bound(tcx, ty::INNERMOST, br).into() - } - CanonicalVarKind::Effect => ty::Const::new_bound( - tcx, - ty::INNERMOST, - ty::BoundVar::from_usize(i), - tcx.types.bool, - ) - .into(), - CanonicalVarKind::Const(_, ty) - | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound( - tcx, - ty::INNERMOST, - ty::BoundVar::from_usize(i), - ty, - ) - .into(), - } - }, - )), - } - } - - /// Creates dummy var values which should not be used in a - /// canonical response. - pub fn dummy() -> CanonicalVarValues<'tcx> { - CanonicalVarValues { var_values: ty::List::empty() } - } - - #[inline] - pub fn len(&self) -> usize { - self.var_values.len() - } -} - -impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> { - type Item = GenericArg<'tcx>; - type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>; - - fn into_iter(self) -> Self::IntoIter { - self.var_values.iter() - } -} - -impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> { - type Output = GenericArg<'tcx>; - - fn index(&self, value: BoundVar) -> &GenericArg<'tcx> { - &self.var_values[value.as_usize()] - } -} - #[derive(Default)] pub struct CanonicalParamEnvCache<'tcx> { map: Lock< diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index fb796bf87a1..62e71c4db11 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -9,7 +9,6 @@ pub mod specialization_graph; mod structural_impls; pub mod util; -use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::GenericArgsRef; @@ -32,6 +31,8 @@ use std::borrow::Cow; use std::hash::{Hash, Hasher}; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; +// FIXME: Remove this import and import via `solve::` +pub use rustc_next_trait_solver::solve::BuiltinImplSource; /// Depending on the stage of compilation, we want projection to be /// more or less conservative. @@ -736,32 +737,6 @@ pub struct ImplSourceUserDefinedData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Copy, Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum BuiltinImplSource { - /// Some builtin impl we don't need to differentiate. This should be used - /// unless more specific information is necessary. - Misc, - /// A builtin impl for trait objects. - /// - /// The vtable is formed by concatenating together the method lists of - /// the base object trait and all supertraits, pointers to supertrait vtable will - /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods - /// in that vtable. - Object { vtable_base: usize }, - /// The vtable is formed by concatenating together the method lists of - /// the base object trait and all supertraits, pointers to supertrait vtable will - /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable - /// within that vtable. - TraitUpcasting { vtable_vptr_slot: Option<usize> }, - /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`. - /// - /// This needs to be a separate variant as it is still unstable and we need to emit - /// a feature error when using it on stable. - TupleUnsizing, -} - -TrivialTypeTraversalImpls! { BuiltinImplSource } - #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 70f3532e3ab..66e50307733 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -12,6 +12,8 @@ use crate::ty::GenericArg; use crate::ty::{self, Ty, TyCtxt}; use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_span::Span; +// FIXME: Remove this import and import via `traits::solve`. +pub use rustc_next_trait_solver::solve::NoSolution; pub mod type_op { use crate::ty::fold::TypeFoldable; @@ -89,9 +91,6 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>; -#[derive(Copy, Clone, Debug, Hash, HashStable, PartialEq, Eq)] -pub struct NoSolution; - impl<'tcx> From<TypeError<'tcx>> for NoSolution { fn from(_: TypeError<'tcx>) -> NoSolution { NoSolution diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 3ad6b68d129..c8c16ec1e2c 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,122 +1,24 @@ use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; -use rustc_span::def_id::DefId; +use rustc_next_trait_solver as ir; +pub use rustc_next_trait_solver::solve::*; -use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; -use crate::traits::query::NoSolution; -use crate::traits::Canonical; +use crate::infer::canonical::QueryRegionConstraints; use crate::ty::{ - self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, - TypeVisitor, + self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; -use super::BuiltinImplSource; - mod cache; -pub mod inspect; pub use cache::{CacheData, EvaluationCache}; -/// A goal is a statement, i.e. `predicate`, we want to prove -/// given some assumptions, i.e. `param_env`. -/// -/// Most of the time the `param_env` contains the `where`-bounds of the function -/// we're currently typechecking while the `predicate` is some trait bound. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct Goal<'tcx, P> { - pub predicate: P, - pub param_env: ty::ParamEnv<'tcx>, -} - -impl<'tcx, P> Goal<'tcx, P> { - pub fn new( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - predicate: impl ToPredicate<'tcx, P>, - ) -> Goal<'tcx, P> { - Goal { param_env, predicate: predicate.to_predicate(tcx) } - } - - /// Updates the goal to one with a different `predicate` but the same `param_env`. - pub fn with<Q>(self, tcx: TyCtxt<'tcx>, predicate: impl ToPredicate<'tcx, Q>) -> Goal<'tcx, Q> { - Goal { param_env: self.param_env, predicate: predicate.to_predicate(tcx) } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct Response<'tcx> { - pub certainty: Certainty, - pub var_values: CanonicalVarValues<'tcx>, - /// Additional constraints returned by this query. - pub external_constraints: ExternalConstraints<'tcx>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum Certainty { - Yes, - Maybe(MaybeCause), -} - -impl Certainty { - pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity); - - /// Use this function to merge the certainty of multiple nested subgoals. - /// - /// Given an impl like `impl<T: Foo + Bar> Baz for T {}`, we have 2 nested - /// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`. - /// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in - /// success, we merge these two responses. This results in ambiguity. - /// - /// If we unify ambiguity with overflow, we return overflow. This doesn't matter - /// inside of the solver as we do not distinguish ambiguity from overflow. It does - /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` - /// in ambiguity without changing the inference state, we still want to tell the - /// user that `T: Baz` results in overflow. - pub fn unify_with(self, other: Certainty) -> Certainty { - match (self, other) { - (Certainty::Yes, Certainty::Yes) => Certainty::Yes, - (Certainty::Yes, Certainty::Maybe(_)) => other, - (Certainty::Maybe(_), Certainty::Yes) => self, - (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.unify_with(b)), - } - } - - pub const fn overflow(suggest_increasing_limit: bool) -> Certainty { - Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }) - } -} - -/// Why we failed to evaluate a goal. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum MaybeCause { - /// We failed due to ambiguity. This ambiguity can either - /// be a true ambiguity, i.e. there are multiple different answers, - /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals. - Ambiguity, - /// We gave up due to an overflow, most often by hitting the recursion limit. - Overflow { suggest_increasing_limit: bool }, -} - -impl MaybeCause { - fn unify_with(self, other: MaybeCause) -> MaybeCause { - match (self, other) { - (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, - (MaybeCause::Ambiguity, MaybeCause::Overflow { .. }) => other, - (MaybeCause::Overflow { .. }, MaybeCause::Ambiguity) => self, - ( - MaybeCause::Overflow { suggest_increasing_limit: a }, - MaybeCause::Overflow { suggest_increasing_limit: b }, - ) => MaybeCause::Overflow { suggest_increasing_limit: a || b }, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct QueryInput<'tcx, T> { - pub goal: Goal<'tcx, T>, - pub predefined_opaques_in_body: PredefinedOpaques<'tcx>, -} +pub type Goal<'tcx, P> = ir::solve::Goal<TyCtxt<'tcx>, P>; +pub type QueryInput<'tcx, P> = ir::solve::QueryInput<TyCtxt<'tcx>, P>; +pub type QueryResult<'tcx> = ir::solve::QueryResult<TyCtxt<'tcx>>; +pub type CandidateSource<'tcx> = ir::solve::CandidateSource<TyCtxt<'tcx>>; +pub type CanonicalInput<'tcx, P = ty::Predicate<'tcx>> = ir::solve::CanonicalInput<TyCtxt<'tcx>, P>; +pub type CanonicalResponse<'tcx> = ir::solve::CanonicalResponse<TyCtxt<'tcx>>; /// Additional constraints returned on success. #[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)] @@ -135,18 +37,6 @@ impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> { } } -pub type CanonicalInput<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, QueryInput<'tcx, T>>; - -pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>; - -/// The result of evaluating a canonical query. -/// -/// FIXME: We use a different type than the existing canonical queries. This is because -/// we need to add a `Certainty` for `overflow` and may want to restructure this code without -/// having to worry about changes to currently used code. Once we've made progress on this -/// solver, merge the two responses again. -pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>; - #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)] pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); @@ -253,91 +143,3 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> { self.opaque_types.visit_with(visitor) } } - -/// Why a specific goal has to be proven. -/// -/// This is necessary as we treat nested goals different depending on -/// their source. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeVisitable, TypeFoldable)] -pub enum GoalSource { - Misc, - /// We're proving a where-bound of an impl. - /// - /// FIXME(-Znext-solver=coinductive): Explain how and why this - /// changes whether cycles are coinductive. - /// - /// This also impacts whether we erase constraints on overflow. - /// Erasing constraints is generally very useful for perf and also - /// results in better error messages by avoiding spurious errors. - /// We do not erase overflow constraints in `normalizes-to` goals unless - /// they are from an impl where-clause. This is necessary due to - /// backwards compatability, cc trait-system-refactor-initiatitive#70. - ImplWhereBound, - /// Instantiating a higher-ranked goal and re-proving it. - InstantiateHigherRanked, -} - -/// Possible ways the given goal can be proven. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CandidateSource { - /// A user written impl. - /// - /// ## Examples - /// - /// ```rust - /// fn main() { - /// let x: Vec<u32> = Vec::new(); - /// // This uses the impl from the standard library to prove `Vec<T>: Clone`. - /// let y = x.clone(); - /// } - /// ``` - Impl(DefId), - /// A builtin impl generated by the compiler. When adding a new special - /// trait, try to use actual impls whenever possible. Builtin impls should - /// only be used in cases where the impl cannot be manually be written. - /// - /// Notable examples are auto traits, `Sized`, and `DiscriminantKind`. - /// For a list of all traits with builtin impls, check out the - /// `EvalCtxt::assemble_builtin_impl_candidates` method. - BuiltinImpl(BuiltinImplSource), - /// An assumption from the environment. - /// - /// More precisely we've used the `n-th` assumption in the `param_env`. - /// - /// ## Examples - /// - /// ```rust - /// fn is_clone<T: Clone>(x: T) -> (T, T) { - /// // This uses the assumption `T: Clone` from the `where`-bounds - /// // to prove `T: Clone`. - /// (x.clone(), x) - /// } - /// ``` - ParamEnv(usize), - /// If the self type is an alias type, e.g. an opaque type or a projection, - /// we know the bounds on that alias to hold even without knowing its concrete - /// underlying type. - /// - /// More precisely this candidate is using the `n-th` bound in the `item_bounds` of - /// the self type. - /// - /// ## Examples - /// - /// ```rust - /// trait Trait { - /// type Assoc: Clone; - /// } - /// - /// fn foo<T: Trait>(x: <T as Trait>::Assoc) { - /// // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in - /// // in the trait definition. - /// let _y = x.clone(); - /// } - /// ``` - AliasBound, - /// A candidate that is registered only during coherence to represent some - /// yet-unknown impl that could be produced downstream without violating orphan - /// rules. - // FIXME: Merge this with the forced ambiguity candidates, so those don't use `Misc`. - CoherenceUnknowable, -} diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs index 4f90af0a27c..03ce7cf98cf 100644 --- a/compiler/rustc_middle/src/traits/solve/cache.rs +++ b/compiler/rustc_middle/src/traits/solve/cache.rs @@ -17,7 +17,7 @@ pub struct EvaluationCache<'tcx> { #[derive(PartialEq, Eq)] pub struct CacheData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>, + pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>, pub reached_depth: usize, pub encountered_overflow: bool, } @@ -28,7 +28,7 @@ impl<'tcx> EvaluationCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: CanonicalInput<'tcx>, - proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>, + proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>, reached_depth: usize, encountered_overflow: bool, cycle_participants: FxHashSet<CanonicalInput<'tcx>>, @@ -105,7 +105,7 @@ struct Success<'tcx> { #[derive(Clone, Copy)] pub struct QueryData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>, + pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>, } /// The cache entry for a goal `CanonicalInput`. diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index 3419827a742..707e076921b 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashSet; -use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt}; +use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, TyCtxt, Upcast}; /// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition. /// @@ -11,7 +11,7 @@ pub fn super_predicates_for_pretty_printing<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: PolyTraitRef<'tcx>, ) -> impl Iterator<Item = Clause<'tcx>> { - let clause = trait_ref.to_predicate(tcx); + let clause = trait_ref.upcast(tcx); Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] } } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 9badf65115e..6d7b6259747 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -15,7 +15,7 @@ pub enum PointerCoercion { /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer. /// It cannot convert a closure that requires unsafe. - ClosureFnPointer(hir::Unsafety), + ClosureFnPointer(hir::Safety), /// Go from a mut raw pointer to a const raw pointer. MutToConstPointer, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d7e185dd5e1..69681930be6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -89,20 +89,26 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; - type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>; type AdtDef = ty::AdtDef<'tcx>; + type GenericArgs = ty::GenericArgsRef<'tcx>; - type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; + type OwnItemArgs = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; - type Term = ty::Term<'tcx>; + type Binder<T: TypeVisitable<TyCtxt<'tcx>>> = Binder<'tcx, T>; type BoundVars = &'tcx List<ty::BoundVariableKind>; type BoundVar = ty::BoundVariableKind; type CanonicalVars = CanonicalVarInfos<'tcx>; + type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; + type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>; + type ExternalConstraints = ExternalConstraints<'tcx>; + type GoalEvaluationSteps = &'tcx [solve::inspect::GoalEvaluationStep<TyCtxt<'tcx>>]; + type Ty = Ty<'tcx>; type Tys = &'tcx List<Ty<'tcx>>; + type FnInputTys = &'tcx [Ty<'tcx>]; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; @@ -113,21 +119,25 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type AllocId = crate::mir::interpret::AllocId; type Pat = Pattern<'tcx>; + type Safety = hir::Safety; + type Abi = abi::Abi; + type Const = ty::Const<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; type ValueConst = ty::ValTree<'tcx>; - type ExprConst = ty::Expr<'tcx>; + type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; type BoundRegion = ty::BoundRegion; type InferRegion = ty::RegionVid; - type PlaceholderRegion = ty::PlaceholderRegion; + + type ParamEnv = ty::ParamEnv<'tcx>; type Predicate = Predicate<'tcx>; type TraitPredicate = ty::TraitPredicate<'tcx>; type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; @@ -135,10 +145,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; + type CoercePredicate = ty::CoercePredicate<'tcx>; type ClosureKind = ty::ClosureKind; type Clauses = ty::Clauses<'tcx>; + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars { self.mk_canonical_var_infos(infos) } @@ -191,7 +203,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) { + ) -> (rustc_type_ir::TraitRef<Self>, Self::OwnItemArgs) { assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); let trait_def_id = self.parent(def_id); assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); @@ -223,6 +235,18 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } +impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi { + fn is_rust(self) -> bool { + matches!(self, abi::Abi::Rust) + } +} + +impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety { + fn prefix_str(self) -> &'static str { + self.prefix_str() + } +} + type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; pub struct CtxtInterners<'tcx> { @@ -2006,11 +2030,8 @@ impl<'tcx> TyCtxt<'tcx> { /// that is, a `fn` type that is equivalent in every way for being /// unsafe. pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { - assert_eq!(sig.unsafety(), hir::Unsafety::Normal); - Ty::new_fn_ptr( - self, - sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }), - ) + assert_eq!(sig.safety(), hir::Safety::Safe); + Ty::new_fn_ptr(self, sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Unsafe, ..sig })) } /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` @@ -2067,20 +2088,16 @@ impl<'tcx> TyCtxt<'tcx> { /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then /// you would get a `fn(u32, i32)`. /// `unsafety` determines the unsafety of the fn signature. If you pass - /// `hir::Unsafety::Unsafe` in the previous example, then you would get + /// `hir::Safety::Unsafe` in the previous example, then you would get /// an `unsafe fn (u32, i32)`. /// It cannot convert a closure that requires unsafe. - pub fn signature_unclosure( - self, - sig: PolyFnSig<'tcx>, - unsafety: hir::Unsafety, - ) -> PolyFnSig<'tcx> { + pub fn signature_unclosure(self, sig: PolyFnSig<'tcx>, safety: hir::Safety) -> PolyFnSig<'tcx> { sig.map_bound(|s| { let params = match s.inputs()[0].kind() { ty::Tuple(params) => *params, _ => bug!(), }; - self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust) + self.mk_fn_sig(params, s.output(), s.c_variadic, safety, abi::Abi::Rust) }) } @@ -2347,7 +2364,7 @@ impl<'tcx> TyCtxt<'tcx> { inputs: I, output: I::Item, c_variadic: bool, - unsafety: hir::Unsafety, + safety: hir::Safety, abi: abi::Abi, ) -> T::Output where @@ -2357,7 +2374,7 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig { inputs_and_output: self.mk_type_list(xs), c_variadic, - unsafety, + safety, abi, }) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 71437ce1df9..99d703be873 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -34,7 +34,7 @@ pub enum TypeError<'tcx> { Mismatch, ConstnessMismatch(ExpectedFound<ty::BoundConstness>), PolarityMismatch(ExpectedFound<ty::PredicatePolarity>), - UnsafetyMismatch(ExpectedFound<hir::Unsafety>), + SafetyMismatch(ExpectedFound<hir::Safety>), AbiMismatch(ExpectedFound<abi::Abi>), Mutability, ArgumentMutability(usize), @@ -107,7 +107,7 @@ impl<'tcx> TypeError<'tcx> { format!("expected {} polarity, found {} polarity", values.expected, values.found) .into() } - UnsafetyMismatch(values) => { + SafetyMismatch(values) => { format!("expected {} fn, found {} fn", values.expected, values.found).into() } AbiMismatch(values) => { @@ -204,7 +204,7 @@ impl<'tcx> TypeError<'tcx> { pub fn must_include_note(self) -> bool { use self::TypeError::*; match self { - CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_) + CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_) | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false, diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 8d7489f5f7e..7508f0080cc 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -281,13 +281,13 @@ impl DeepRejectCtxt { } ty::FnPtr(obl_sig) => match k { ty::FnPtr(impl_sig) => { - let ty::FnSig { inputs_and_output, c_variadic, unsafety, abi } = + let ty::FnSig { inputs_and_output, c_variadic, safety, abi } = obl_sig.skip_binder(); let impl_sig = impl_sig.skip_binder(); abi == impl_sig.abi && c_variadic == impl_sig.c_variadic - && unsafety == impl_sig.unsafety + && safety == impl_sig.safety && inputs_and_output.len() == impl_sig.inputs_and_output.len() && iter::zip(inputs_and_output, impl_sig.inputs_and_output) .all(|(obl, imp)| self.types_may_unify(obl, imp)) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 904c0c332a8..38b2987399a 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -11,6 +11,7 @@ use rustc_ast_ir::walk_visitable_list; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; +use rustc_macros::extension; use rustc_macros::{ Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, }; @@ -25,6 +26,8 @@ use std::num::NonZero; use std::ops::Deref; use std::ptr::NonNull; +pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>; + /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts). /// To reduce memory usage, a `GenericArg` is an interned pointer, @@ -49,6 +52,14 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg } } +impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> { + type Kind = GenericArgKind<'tcx>; + + fn kind(self) -> Self::Kind { + self.unpack() + } +} + #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend @@ -79,13 +90,7 @@ const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; const CONST_TAG: usize = 0b10; -#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, HashStable)] -pub enum GenericArgKind<'tcx> { - Lifetime(ty::Region<'tcx>), - Type(Ty<'tcx>), - Const(ty::Const<'tcx>), -} - +#[extension(trait GenericArgPackExt<'tcx>)] impl<'tcx> GenericArgKind<'tcx> { #[inline] fn pack(self) -> GenericArg<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 93ccc0a7de4..ce63fc20ddb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,7 +28,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::util::Discr; pub use adt::*; pub use assoc::*; -pub use generic_args::*; +pub use generic_args::{GenericArgKind, *}; pub use generics::*; pub use intrinsic::IntrinsicDef; use rustc_ast as ast; @@ -102,7 +102,7 @@ pub use self::predicate::{ PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, - ToPredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate, + TraitPredicate, TraitRef, TypeOutlivesPredicate, }; pub use self::region::{ BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region, @@ -266,7 +266,7 @@ pub struct ImplHeader<'tcx> { pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, - pub unsafety: hir::Unsafety, + pub safety: hir::Safety, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 16ca098853e..644fca7c5fe 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -9,7 +9,7 @@ use std::cmp::Ordering; use crate::ty::{ self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, - WithCachedTypeInfo, + Upcast, UpcastFrom, WithCachedTypeInfo, }; pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>; @@ -234,10 +234,10 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { match self.skip_binder() { ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) + self.rebind(tr).with_self_ty(tcx, self_ty).upcast(tcx) } ExistentialPredicate::Projection(p) => { - self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) + self.rebind(p.with_self_ty(tcx, self_ty)).upcast(tcx) } ExistentialPredicate::AutoTrait(did) => { let generics = tcx.generics_of(did); @@ -249,7 +249,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); ty::TraitRef::new(tcx, did, err_args) }; - self.rebind(trait_ref).to_predicate(tcx) + self.rebind(trait_ref).upcast(tcx) } } } @@ -544,185 +544,164 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; -} - -impl<'tcx, T> ToPredicate<'tcx, T> for T { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { - self +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + ty::Binder::dummy(from).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> { + fn upcast_from(from: Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + tcx.mk_predicate(from) } } -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))) } } -impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> { + fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + tcx.mk_predicate(from.map_bound(PredicateKind::Clause)) } } -impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.as_predicate() +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self { + from.as_predicate() } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> { + fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(from))).expect_clause() } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> { + fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause() } } -impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + ty::Binder::dummy(from).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { - TraitPredicate { trait_ref: self, polarity: PredicatePolarity::Positive } +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for TraitPredicate<'tcx> { + fn upcast_from(from: TraitRef<'tcx>, _tcx: TyCtxt<'tcx>) -> Self { + TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive } } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> { + fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let p: Predicate<'tcx> = from.upcast(tcx); p.expect_clause() } } -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> { + fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx); + pred.upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> { + fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx); + pred.upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| TraitPredicate { +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> { + fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self { + from.map_bound(|trait_ref| TraitPredicate { trait_ref, - polarity: ty::PredicatePolarity::Positive, + polarity: PredicatePolarity::Positive, }) } } -impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> { + fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let p: Predicate<'tcx> = from.upcast(tcx); p.expect_clause() } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> { + fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let p: Predicate<'tcx> = from.upcast(tcx); p.expect_clause() } } -impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + for Predicate<'tcx> +{ + fn upcast_from(from: OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx) } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> { + fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let p: Predicate<'tcx> = from.upcast(tcx); p.expect_clause() } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> { + fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let p: Predicate<'tcx> = from.upcast(tcx); p.expect_clause() } } -impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::NormalizesTo(self).to_predicate(tcx) +impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + PredicateKind::NormalizesTo(from).upcast(tcx) } } impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> { + pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), @@ -742,7 +721,7 @@ impl<'tcx> Predicate<'tcx> { } } - pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> { + pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3577db7234d..0dbb17e9db4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3034,6 +3034,16 @@ forward_display_to_print! { define_print! { (self, cx): + ty::FnSig<'tcx> { + p!(write("{}", self.safety.prefix_str())); + + if self.abi != Abi::Rust { + p!(write("extern {} ", self.abi)); + } + + p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); + } + ty::TraitRef<'tcx> { p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) } @@ -3169,16 +3179,6 @@ define_print_and_forward_display! { p!("{{", comma_sep(self.iter()), "}}") } - ty::FnSig<'tcx> { - p!(write("{}", self.unsafety.prefix_str())); - - if self.abi != Abi::Rust { - p!(write("extern {} ", self.abi)); - } - - p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); - } - TraitRefPrintOnlyTraitPath<'tcx> { p!(print_def_path(self.0.def_id, self.0.args)); } diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 8842ecd12e9..7540f0ab83f 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -396,6 +396,12 @@ pub struct BoundRegion { pub kind: BoundRegionKind, } +impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion { + fn var(self) -> BoundVar { + self.var + } +} + impl core::fmt::Debug for BoundRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.kind { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index eaf5fdf5710..947de3f3aaa 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -146,7 +146,7 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { if a.c_variadic != b.c_variadic { return Err(TypeError::VariadicMismatch(expected_found(a.c_variadic, b.c_variadic))); } - let unsafety = relation.relate(a.unsafety, b.unsafety)?; + let safety = relation.relate(a.safety, b.safety)?; let abi = relation.relate(a.abi, b.abi)?; if a.inputs().len() != b.inputs().len() { @@ -181,7 +181,7 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { Ok(ty::FnSig { inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?, c_variadic: a.c_variadic, - unsafety, + safety, abi, }) } @@ -197,13 +197,13 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness { } } -impl<'tcx> Relate<'tcx> for hir::Unsafety { +impl<'tcx> Relate<'tcx> for hir::Safety { fn relate<R: TypeRelation<'tcx>>( _relation: &mut R, - a: hir::Unsafety, - b: hir::Unsafety, - ) -> RelateResult<'tcx, hir::Unsafety> { - if a != b { Err(TypeError::UnsafetyMismatch(expected_found(a, b))) } else { Ok(a) } + a: hir::Safety, + b: hir::Safety, + ) -> RelateResult<'tcx, hir::Safety> { + if a != b { Err(TypeError::SafetyMismatch(expected_found(a, b))) } else { Ok(a) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7523cd15320..7d24824d568 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -83,49 +83,6 @@ impl fmt::Debug for ty::LateParamRegion { } } -impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - WithInfcx::with_no_infcx(self).fmt(f) - } -} -impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::FnSig<'tcx> { - fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - let sig = this.data; - let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = sig; - - write!(f, "{}", unsafety.prefix_str())?; - match abi { - rustc_target::spec::abi::Abi::Rust => (), - abi => write!(f, "extern \"{abi:?}\" ")?, - }; - - write!(f, "fn(")?; - let inputs = sig.inputs(); - match inputs.len() { - 0 if *c_variadic => write!(f, "...)")?, - 0 => write!(f, ")")?, - _ => { - for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] { - write!(f, "{:?}, ", &this.wrap(ty))?; - } - write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?; - if *c_variadic { - write!(f, "...")?; - } - write!(f, ")")?; - } - } - - match sig.output().kind() { - ty::Tuple(list) if list.is_empty() => Ok(()), - _ => write!(f, " -> {:?}", &this.wrap(sig.output())), - } - } -} - impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> { fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>( this: WithInfcx<'_, Infcx, &Self>, @@ -398,7 +355,7 @@ TrivialTypeTraversalImpls! { // interners). TrivialTypeTraversalAndLiftImpls! { ::rustc_hir::def_id::DefId, - ::rustc_hir::Unsafety, + ::rustc_hir::Safety, ::rustc_target::spec::abi::Abi, crate::ty::ClosureKind, crate::ty::ParamConst, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74b03d6db66..7c41c5f512e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -39,6 +39,7 @@ use super::GenericParamDefKind; pub type TyKind<'tcx> = ir::TyKind<TyCtxt<'tcx>>; pub type TypeAndMut<'tcx> = ir::TypeAndMut<TyCtxt<'tcx>>; pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>; +pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>; pub trait Article { fn article(&self) -> &'static str; @@ -387,7 +388,7 @@ impl<'tcx> CoroutineClosureArgs<'tcx> { yield_ty, return_ty, c_variadic: sig.c_variadic, - unsafety: sig.unsafety, + safety: sig.safety, abi: sig.abi, } }) @@ -415,8 +416,8 @@ pub struct CoroutineClosureSignature<'tcx> { // from scratch just for good measure. /// Always false pub c_variadic: bool, - /// Always [`hir::Unsafety::Normal`] - pub unsafety: hir::Unsafety, + /// Always [`hir::Safety::Safe`] + pub safety: hir::Safety, /// Always [`abi::Abi::RustCall`] pub abi: abi::Abi, } @@ -985,14 +986,6 @@ impl<'tcx, T> Binder<'tcx, T> { Binder { value: &self.value, bound_vars: self.bound_vars } } - pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U> - where - F: FnOnce(&T) -> U, - { - let value = f(&self.value); - Binder { value, bound_vars: self.bound_vars } - } - pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, @@ -1109,73 +1102,37 @@ pub struct GenSig<'tcx> { pub return_ty: Ty<'tcx>, } -/// Signature of a function type, which we have arbitrarily -/// decided to use to refer to the input/output types. -/// -/// - `inputs`: is the list of arguments and their modes. -/// - `output`: is the return type. -/// - `c_variadic`: indicates whether this is a C-variadic function. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct FnSig<'tcx> { - pub inputs_and_output: &'tcx List<Ty<'tcx>>, - pub c_variadic: bool, - pub unsafety: hir::Unsafety, - pub abi: abi::Abi, -} - -impl<'tcx> FnSig<'tcx> { - pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { - &self.inputs_and_output[..self.inputs_and_output.len() - 1] - } - - pub fn output(&self) -> Ty<'tcx> { - self.inputs_and_output[self.inputs_and_output.len() - 1] - } - - // Creates a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible - // method. - fn fake() -> FnSig<'tcx> { - FnSig { - inputs_and_output: List::empty(), - c_variadic: false, - unsafety: hir::Unsafety::Normal, - abi: abi::Abi::Rust, - } - } -} - -impl<'tcx> IntoDiagArg for FnSig<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() - } -} - pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { #[inline] pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { - self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) + self.map_bound_ref(|fn_sig| fn_sig.inputs()) } + #[inline] #[track_caller] pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } + pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List<Ty<'tcx>>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } + #[inline] pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output()) } + pub fn c_variadic(&self) -> bool { self.skip_binder().c_variadic } - pub fn unsafety(&self) -> hir::Unsafety { - self.skip_binder().unsafety + + pub fn safety(&self) -> hir::Safety { + self.skip_binder().safety } + pub fn abi(&self) -> abi::Abi { self.skip_binder().abi } @@ -1183,12 +1140,7 @@ impl<'tcx> PolyFnSig<'tcx> { pub fn is_fn_trait_compatible(&self) -> bool { matches!( self.skip_binder(), - ty::FnSig { - unsafety: rustc_hir::Unsafety::Normal, - abi: Abi::Rust, - c_variadic: false, - .. - } + ty::FnSig { safety: rustc_hir::Safety::Safe, abi: Abi::Rust, c_variadic: false, .. } ) } } @@ -1247,6 +1199,12 @@ pub struct BoundTy { pub kind: BoundTyKind, } +impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy { + fn var(self) -> BoundVar { + self.var + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundTyKind { @@ -1649,6 +1607,10 @@ impl<'tcx> Ty<'tcx> { } impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> { + fn new_bool(tcx: TyCtxt<'tcx>) -> Self { + tcx.types.bool + } + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) } @@ -2031,7 +1993,12 @@ impl<'tcx> Ty<'tcx> { FnPtr(f) => *f, Error(_) => { // ignore errors (#54954) - ty::Binder::dummy(FnSig::fake()) + ty::Binder::dummy(ty::FnSig { + inputs_and_output: ty::List::empty(), + c_variadic: false, + safety: hir::Safety::Safe, + abi: abi::Abi::Rust, + }) } Closure(..) => bug!( "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", @@ -2624,6 +2591,13 @@ impl<'tcx> Ty<'tcx> { } } +impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> { + fn split_inputs_and_output(self) -> (&'tcx [Ty<'tcx>], Ty<'tcx>) { + let (output, inputs) = self.split_last().unwrap(); + (inputs, *output) + } +} + /// Extra information about why we ended up with a particular variance. /// This is only used to add more information to error messages, and /// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo` diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index cf5decffea9..c5b3de17bcb 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -15,7 +15,7 @@ use rustc_macros::{Decodable, Encodable, HashStable}; pub struct TraitDef { pub def_id: DefId, - pub unsafety: hir::Unsafety, + pub safety: hir::Safety, /// If `true`, then this trait had the `#[rustc_paren_sugar]` /// attribute, indicating that it should be used with `Foo()` diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7f3d6a713d9..8c14f1e080a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -4,8 +4,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::{IntoQueryParam, Providers}; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ - self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, Upcast, }; use crate::ty::{GenericArgKind, GenericArgsRef}; use rustc_apfloat::Float as _; @@ -1094,7 +1094,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { // anything that requires `ParamEnv::with_reveal_all_normalized`. term: projection_pred.term, }) - .to_predicate(self.tcx) + .upcast(self.tcx) } else { p.super_fold_with(self) } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index e3866b27cee..79f36cfe569 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -65,7 +65,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> { std::iter::repeat(err).take(arity), err, false, - rustc_hir::Unsafety::Normal, + rustc_hir::Safety::Safe, rustc_target::spec::abi::Abi::Rust, )); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b9990d65ec7..b5f7ffbd2af 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -391,7 +391,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { return; // don't visit the whole expression } ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { - if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + if self.thir[fun].ty.fn_sig(self.tcx).safety() == hir::Safety::Unsafe { let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() { Some(*func_id) } else { @@ -921,7 +921,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let hir_id = tcx.local_def_id_to_hir_id(def); let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { - if fn_sig.header.unsafety == hir::Unsafety::Unsafe { + if fn_sig.header.safety == hir::Safety::Unsafe { SafetyContext::UnsafeFn } else { SafetyContext::Safe diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 30b1ca67800..434529ccff4 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -158,7 +158,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { .lint_root; // FIXME: use existing printing routines to print the function signature let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args); - let unsafety = fn_sig.unsafety().prefix_str(); + let unsafety = fn_sig.safety().prefix_str(); let abi = match fn_sig.abi() { Abi::Rust => String::from(""), other_abi => { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index cd8a43d6e6c..dcf54ad2cfc 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1047,7 +1047,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( args.as_coroutine_closure().coroutine_captures_by_ref_ty(), ), sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ) }); diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 9d496fd8e81..8bcc21d82f8 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -5,9 +5,19 @@ edition = "2021" [dependencies] rustc_type_ir = { path = "../rustc_type_ir", default-features = false } +derivative = "2.2.0" +rustc_macros = { path = "../rustc_macros", optional = true } +rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } +rustc_serialize = { path = "../rustc_serialize", optional = true } +rustc_data_structures = { path = "../rustc_data_structures", optional = true } +rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } [features] default = ["nightly"] nightly = [ "rustc_type_ir/nightly", -] \ No newline at end of file + "rustc_macros", + "rustc_serialize", + "rustc_data_structures", + "rustc_ast_ir/nightly", +] diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index e5fc8f755e0..4202dc39fb2 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -1 +1,2 @@ pub mod canonicalizer; +pub mod solve; diff --git a/compiler/rustc_next_trait_solver/src/solve.rs b/compiler/rustc_next_trait_solver/src/solve.rs new file mode 100644 index 00000000000..eba96facabc --- /dev/null +++ b/compiler/rustc_next_trait_solver/src/solve.rs @@ -0,0 +1 @@ +pub use rustc_type_ir::solve::*; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3e1be6461eb..a46c104b6d9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -33,7 +33,7 @@ impl<'a> Parser<'a> { /// Parses a `mod <foo> { ... }` or `mod <foo>;` item. fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(Case::Sensitive); + let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; let mod_kind = if self.eat(&token::Semi) { @@ -45,7 +45,7 @@ impl<'a> Parser<'a> { attrs.extend(inner_attrs); ModKind::Loaded(items, Inline::Yes, inner_span) }; - Ok((id, ItemKind::Mod(unsafety, mod_kind))) + Ok((id, ItemKind::Mod(safety, mod_kind))) } /// Parses the contents of a module (inner attributes followed by module items). @@ -211,13 +211,13 @@ impl<'a> Parser<'a> { self.parse_item_extern_crate()? } else { // EXTERN BLOCK - self.parse_item_foreign_mod(attrs, Unsafe::No)? + self.parse_item_foreign_mod(attrs, Safety::Default)? } } else if self.is_unsafe_foreign_mod() { // EXTERN BLOCK - let unsafety = self.parse_unsafety(Case::Sensitive); + let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(kw::Extern)?; - self.parse_item_foreign_mod(attrs, unsafety)? + self.parse_item_foreign_mod(attrs, safety)? } else if self.is_static_global() { // STATIC ITEM self.bump(); // `static` @@ -541,7 +541,7 @@ impl<'a> Parser<'a> { attrs: &mut AttrVec, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(Case::Sensitive); + let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(kw::Impl)?; // First, parse generic parameters if necessary. @@ -647,7 +647,7 @@ impl<'a> Parser<'a> { let trait_ref = TraitRef { path, ref_id: ty_first.id }; ItemKind::Impl(Box::new(Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -660,7 +660,7 @@ impl<'a> Parser<'a> { None => { // impl Type ItemKind::Impl(Box::new(Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -865,7 +865,7 @@ impl<'a> Parser<'a> { /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { - let unsafety = self.parse_unsafety(Case::Sensitive); + let safety = self.parse_safety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span); @@ -899,7 +899,7 @@ impl<'a> Parser<'a> { if is_auto == IsAuto::Yes { self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span }); } - if let Unsafe::Yes(_) = unsafety { + if let Safety::Unsafe(_) = safety { self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span }); } @@ -912,7 +912,7 @@ impl<'a> Parser<'a> { let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; Ok(( ident, - ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })), + ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })), )) } } @@ -1173,19 +1173,19 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, attrs: &mut AttrVec, - mut unsafety: Unsafe, + mut safety: Safety, ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - if unsafety == Unsafe::No + if safety == Safety::Default && self.token.is_keyword(kw::Unsafe) && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace)) { self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit(); - unsafety = Unsafe::Yes(self.token.span); + safety = Safety::Unsafe(self.token.span); self.eat_keyword(kw::Unsafe); } let module = ast::ForeignMod { - unsafety, + safety, abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, }; @@ -2452,7 +2452,7 @@ impl<'a> Parser<'a> { let coroutine_kind = self.parse_coroutine_kind(case); let unsafe_start_sp = self.token.span; - let unsafety = self.parse_unsafety(case); + let safety = self.parse_safety(case); let ext_start_sp = self.token.span; let ext = self.parse_extern(case); @@ -2490,7 +2490,7 @@ impl<'a> Parser<'a> { // We may be able to recover let mut recover_constness = constness; let mut recover_coroutine_kind = coroutine_kind; - let mut recover_unsafety = unsafety; + let mut recover_safety = safety; // This will allow the machine fix to directly place the keyword in the correct place or to indicate // that the keyword is already present and the second instance should be removed. let wrong_kw = if self.check_keyword(kw::Const) { @@ -2528,10 +2528,10 @@ impl<'a> Parser<'a> { } } } else if self.check_keyword(kw::Unsafe) { - match unsafety { - Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), - Unsafe::No => { - recover_unsafety = Unsafe::Yes(self.token.span); + match safety { + Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)), + Safety::Default => { + recover_safety = Safety::Unsafe(self.token.span); Some(WrongKw::Misplaced(ext_start_sp)) } } @@ -2616,7 +2616,7 @@ impl<'a> Parser<'a> { err.emit(); return Ok(FnHeader { constness: recover_constness, - unsafety: recover_unsafety, + safety: recover_safety, coroutine_kind: recover_coroutine_kind, ext, }); @@ -2627,7 +2627,7 @@ impl<'a> Parser<'a> { } } - Ok(FnHeader { constness, unsafety, coroutine_kind, ext }) + Ok(FnHeader { constness, safety, coroutine_kind, ext }) } /// Parses the parameter list and result type of a function declaration. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3e0a98a55ae..c2183258eef 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -26,7 +26,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, - Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, StrLit, Unsafe, Visibility, + Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, DUMMY_NODE_ID, }; use rustc_ast_pretty::pprust; @@ -1217,12 +1217,12 @@ impl<'a> Parser<'a> { } } - /// Parses unsafety: `unsafe` or nothing. - fn parse_unsafety(&mut self, case: Case) -> Unsafe { + /// Parses fn unsafety: `unsafe`, `safe` or nothing. + fn parse_safety(&mut self, case: Case) -> Safety { if self.eat_keyword_case(kw::Unsafe, case) { - Unsafe::Yes(self.prev_token.uninterpolated_span()) + Safety::Unsafe(self.prev_token.uninterpolated_span()) } else { - Unsafe::No + Safety::Default } } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index a6f0ab78b5c..619c4c63e51 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -36,13 +36,19 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr => { + NonterminalKind::Expr2021 => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } + NonterminalKind::Expr => { + token.can_begin_expr() + // This exception is here for backwards compatibility. + && !token.is_keyword(kw::Let) + && (token.span.edition().at_least_rust_2024() || !token.is_keyword(kw::Const)) + } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), @@ -143,7 +149,9 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NtExpr(self.parse_expr_force_collect()?) + } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 2f08a48c7bc..2df8f58507b 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -590,7 +590,7 @@ impl<'a> Parser<'a> { tokens: None, }; let span_start = self.token.span; - let ast::FnHeader { ext, unsafety, constness, coroutine_kind } = + let ast::FnHeader { ext, safety, constness, coroutine_kind } = self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?; if self.may_recover() && self.token.kind == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; @@ -608,7 +608,7 @@ impl<'a> Parser<'a> { } // FIXME(gen_blocks): emit a similar error for `gen fn()` let decl_span = span_start.to(self.token.span); - Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span }))) + Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span }))) } /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`). diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e60aa27dba2..aadbd747313 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -17,7 +17,7 @@ use rustc_hir::{self as hir}; use rustc_hir::{ self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, }; -use rustc_hir::{MethodKind, Target, Unsafety}; +use rustc_hir::{MethodKind, Safety, Target}; use rustc_macros::LintDiagnostic; use rustc_middle::bug; use rustc_middle::hir::nested_filter; @@ -2335,7 +2335,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }), token_stream, false, - Unsafety::Normal, + Safety::Safe, Abi::Rust, ); @@ -2362,7 +2362,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { cause.span = ty.span; } } - TypeError::UnsafetyMismatch(_) => { + TypeError::SafetyMismatch(_) => { // FIXME: Would be nice if we had a span here.. } TypeError::AbiMismatch(_) => { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3e9aa3e0a6f..689109b2840 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -32,6 +32,8 @@ use rustc_span::Span; use std::cell::Cell; +use tracing::debug; + type Res = def::Res<NodeId>; impl<'a, Id: Into<DefId>> ToNameBinding<'a> diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 741a650da55..bd062242856 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; +use tracing::debug; pub(crate) fn collect_definitions( resolver: &mut Resolver<'_, '_>, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 01e279b6d04..b28312fa473 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -28,6 +28,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use thin_vec::{thin_vec, ThinVec}; +use tracing::debug; use crate::errors::{ self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, @@ -43,9 +44,6 @@ use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, Vis use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet}; use crate::{Segment, UseError}; -#[cfg(test)] -mod tests; - type Res = def::Res<ast::NodeId>; /// A vector of spans and replacements, a message and applicability. @@ -3026,14 +3024,3 @@ fn is_span_suitable_for_use_injection(s: Span) -> bool { // import or other generated ones !s.from_expansion() } - -/// Convert the given number into the corresponding ordinal -pub(crate) fn ordinalize(v: usize) -> String { - let suffix = match ((11..=13).contains(&(v % 100)), v % 10) { - (false, 1) => "st", - (false, 2) => "nd", - (false, 3) => "rd", - _ => "th", - }; - format!("{v}{suffix}") -} diff --git a/compiler/rustc_resolve/src/diagnostics/tests.rs b/compiler/rustc_resolve/src/diagnostics/tests.rs deleted file mode 100644 index 2aa6cc61e46..00000000000 --- a/compiler/rustc_resolve/src/diagnostics/tests.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::ordinalize; - -#[test] -fn test_ordinalize() { - assert_eq!(ordinalize(1), "1st"); - assert_eq!(ordinalize(2), "2nd"); - assert_eq!(ordinalize(3), "3rd"); - assert_eq!(ordinalize(4), "4th"); - assert_eq!(ordinalize(5), "5th"); - // ... - assert_eq!(ordinalize(10), "10th"); - assert_eq!(ordinalize(11), "11th"); - assert_eq!(ordinalize(12), "12th"); - assert_eq!(ordinalize(13), "13th"); - assert_eq!(ordinalize(14), "14th"); - // ... - assert_eq!(ordinalize(20), "20th"); - assert_eq!(ordinalize(21), "21st"); - assert_eq!(ordinalize(22), "22nd"); - assert_eq!(ordinalize(23), "23rd"); - assert_eq!(ordinalize(24), "24th"); - // ... - assert_eq!(ordinalize(30), "30th"); - assert_eq!(ordinalize(31), "31st"); - assert_eq!(ordinalize(32), "32nd"); - assert_eq!(ordinalize(33), "33rd"); - assert_eq!(ordinalize(34), "34th"); - // ... - assert_eq!(ordinalize(7010), "7010th"); - assert_eq!(ordinalize(7011), "7011th"); - assert_eq!(ordinalize(7012), "7012th"); - assert_eq!(ordinalize(7013), "7013th"); - assert_eq!(ordinalize(7014), "7014th"); - // ... - assert_eq!(ordinalize(7020), "7020th"); - assert_eq!(ordinalize(7021), "7021st"); - assert_eq!(ordinalize(7022), "7022nd"); - assert_eq!(ordinalize(7023), "7023rd"); - assert_eq!(ordinalize(7024), "7024th"); -} diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 074bf810eaf..aab4a3366da 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -11,6 +11,7 @@ use rustc_middle::middle::privacy::Level; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility}; use rustc_middle::ty::Visibility; use std::mem; +use tracing::info; #[derive(Clone, Copy)] enum ParentId<'a> { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 43a43e01a9a..f88725830f1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,6 +11,7 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex use rustc_span::sym; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; +use tracing::{debug, instrument}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3d9380a3ebd..f53bcb0e9d0 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -34,6 +34,7 @@ use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; use smallvec::SmallVec; +use tracing::debug; use std::cell::Cell; use std::mem; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 322f2922f92..0f585aafdd5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -30,6 +30,7 @@ use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use smallvec::{smallvec, SmallVec}; +use tracing::{debug, instrument, trace}; use std::assert_matches::debug_assert_matches; use std::borrow::Cow; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 12815291c1d..1958fdf1cbc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -40,6 +40,7 @@ use std::iter; use std::ops::Deref; use thin_vec::ThinVec; +use tracing::debug; use super::NoConstantGenericsReason; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af0b4792136..01bcfec4bdc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -6,9 +6,13 @@ //! //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. +// tidy-alphabetical-start +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] -#![feature(rustdoc_internals)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(extract_if)] @@ -16,18 +20,9 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustc_attrs)] -#![allow(rustdoc::private_intra_doc_links)] -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::potential_query_instability)] -#![allow(rustc::untranslatable_diagnostic)] -#![allow(internal_features)] - -#[macro_use] -extern crate tracing; +#![feature(rustdoc_internals)] +// tidy-alphabetical-end -use errors::{ - ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam, -}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; @@ -60,19 +55,21 @@ use rustc_session::lint::LintBuffer; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; - use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::fmt; +use tracing::debug; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; +use effective_visibilities::EffectiveVisibilitiesVisitor; +use errors::{ + ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam, +}; use imports::{Import, ImportData, ImportKind, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; -use crate::effective_visibilities::EffectiveVisibilitiesVisitor; - type Res = def::Res<NodeId>; mod build_reduced_graph; @@ -964,7 +961,6 @@ struct DeriveData { has_derive_copy: bool, } -#[derive(Clone)] struct MacroData { ext: Lrc<SyntaxExtension>, rule_spans: Vec<(usize, Span)>, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index e3cfe6a6e05..f8d245f94e5 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -328,11 +328,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { UNUSED_MACRO_RULES, node_id, rule_span, - format!( - "{} rule of macro `{}` is never used", - crate::diagnostics::ordinalize(arm_i + 1), - ident.name - ), + format!("rule #{} of macro `{}` is never used", arm_i + 1, ident.name), ); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index aace0f3fef9..66b4981eb55 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -8,6 +8,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use std::mem; use std::ops::Range; +use tracing::{debug, trace}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum DocFragmentKind { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f2bdabbf394..7dd9fdf60f9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -798,6 +798,7 @@ pub enum DumpSolverProofTree { Never, } +#[derive(Clone)] pub enum Input { /// Load source code from a file. File(PathBuf), diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 0893bc31bfa..6b73c1ebd1c 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -216,7 +216,7 @@ impl RustcInternal for FnSig { tcx.lift(rustc_ty::FnSig { inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)), c_variadic: self.c_variadic, - unsafety: self.unsafety.internal(tables, tcx), + safety: self.safety.internal(tables, tcx), abi: self.abi.internal(tables, tcx), }) .unwrap() @@ -481,16 +481,15 @@ impl RustcInternal for Abi { } impl RustcInternal for Safety { - type T<'tcx> = rustc_hir::Unsafety; + type T<'tcx> = rustc_hir::Safety; fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match self { - Safety::Unsafe => rustc_hir::Unsafety::Unsafe, - Safety::Normal => rustc_hir::Unsafety::Normal, + Safety::Unsafe => rustc_hir::Safety::Unsafe, + Safety::Safe => rustc_hir::Safety::Safe, } } } - impl RustcInternal for Span { type T<'tcx> = rustc_span::Span; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 41b0a84dd80..736378a530f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -9,12 +9,12 @@ mod error; mod mir; mod ty; -impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety { +impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; fn stable(&self, _: &mut Tables<'_>) -> Self::T { match self { - rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe, - rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal, + rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe, + rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe, } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 44737e6ce40..d59318be720 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -112,8 +112,8 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { match self { PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, - PointerCoercion::ClosureFnPointer(unsafety) => { - stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables)) + PointerCoercion::ClosureFnPointer(safety) => { + stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables)) } PointerCoercion::MutToConstPointer => { stable_mir::mir::PointerCoercion::MutToConstPointer @@ -215,7 +215,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { FnSig { inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(), c_variadic: self.c_variadic, - unsafety: self.unsafety.stable(tables), + safety: self.safety.stable(tables), abi: self.abi.stable(tables), } } @@ -499,7 +499,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { TraitDecl { def_id: tables.trait_def(self.def_id), - unsafety: self.unsafety.stable(tables), + safety: self.safety.stable(tables), paren_sugar: self.paren_sugar, has_auto_impl: self.has_auto_impl, is_marker: self.is_marker, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d41059e8c24..68b1b32baf2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -782,6 +782,8 @@ symbols! { explicit_tail_calls, export_name, expr, + expr_2021, + expr_fragment_specifier_2024, extended_key_value_attributes, extended_varargs_abi_support, extern_absolute_paths, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 9fb217d2f84..57b1542ff5a 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -424,7 +424,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ty::FnPtr(sig) => { self.push("F"); self.in_binder(&sig, |cx, sig| { - if sig.unsafety == hir::Unsafety::Unsafe { + if sig.safety == hir::Safety::Unsafe { cx.push("U"); } match sig.abi { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8ba945e193c..910c6aeb7d6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -612,6 +612,12 @@ impl LinkSelfContainedDefault { _ => "crt-objects-fallback", } } + + /// Creates a `LinkSelfContainedDefault` enabling the self-contained linker for target specs + /// (the equivalent of `-Clink-self-contained=+linker` on the CLI). + pub fn with_linker() -> LinkSelfContainedDefault { + LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER) + } } bitflags::bitflags! { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 11fb28a9aed..bd12d4d8af0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -18,6 +18,13 @@ pub fn target() -> Target { | SanitizerSet::THREAD; base.supports_xray = true; + // When we're asked to use the `rust-lld` linker by default, set the appropriate lld-using + // linker flavor, and self-contained linker component. + if option_env!("CFG_USE_SELF_CONTAINED_LINKER").is_some() { + base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes); + base.link_self_contained = crate::spec::LinkSelfContainedDefault::with_linker(); + } + Target { llvm_target: "x86_64-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 811eb4c9810..1f4fb57d996 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +derivative = "2.2.0" itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } @@ -21,10 +22,13 @@ rustc_middle = { path = "../rustc_middle" } rustc_next_trait_solver = { path = "../rustc_next_trait_solver" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_query_system = { path = "../rustc_query_system" } +rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } +rustc_type_ir = { path = "../rustc_type_ir" } +rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 3dc55509dad..fc852293dff 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -10,7 +10,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryRes use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_middle::ty::{GenericArg, ToPredicate}; +use rustc_middle::ty::{GenericArg, Upcast}; use rustc_span::DUMMY_SP; use std::fmt::Debug; @@ -63,7 +63,7 @@ impl<'tcx> InferCtxt<'tcx> { cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).to_predicate(self.tcx), + predicate: trait_ref.upcast(self.tcx), }; self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 97bea28f06a..b1dd6ae6611 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -13,7 +13,7 @@ use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{fast_reject, TypeFoldable}; -use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; +use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use std::fmt::Debug; @@ -25,7 +25,7 @@ pub(super) mod structural_traits; /// and the `result` when using the given `source`. #[derive(Debug, Clone)] pub(super) struct Candidate<'tcx> { - pub(super) source: CandidateSource, + pub(super) source: CandidateSource<'tcx>, pub(super) result: CanonicalResponse<'tcx>, } @@ -47,7 +47,7 @@ pub(super) trait GoalKind<'tcx>: /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + source: CandidateSource<'tcx>, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, @@ -58,7 +58,7 @@ pub(super) trait GoalKind<'tcx>: /// goal by equating it with the assumption. fn probe_and_consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, - parent_source: CandidateSource, + parent_source: CandidateSource<'tcx>, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>, @@ -76,7 +76,7 @@ pub(super) trait GoalKind<'tcx>: /// since they're not implied by the well-formedness of the object type. fn probe_and_consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + source: CandidateSource<'tcx>, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, ) -> Result<Candidate<'tcx>, NoSolution> { @@ -286,7 +286,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } - let goal = + let goal: Goal<'tcx, G> = goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty)); // Vars that show up in the rest of the goal substs may have been constrained by // normalizing the self type as well, since type variables are not uniquified. @@ -744,7 +744,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ecx, CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base }), goal, - assumption.to_predicate(tcx), + assumption.upcast(tcx), )); }); } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 9e844d78702..cf826596392 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -7,9 +7,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::bug; use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::{ - self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, -}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast}; use rustc_span::sym; use crate::solve::EvalCtxt; @@ -429,7 +427,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc tcx.require_lang_item(LangItem::AsyncFnKindHelper, None), [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ) - .to_predicate(tcx), + .upcast(tcx), ); coroutine_closure_to_ambiguous_coroutine( @@ -456,7 +454,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc let nested = vec![ bound_sig .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])) - .to_predicate(tcx), + .upcast(tcx), ]; let future_output_def_id = tcx .associated_items(future_trait_def_id) @@ -484,7 +482,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc let mut nested = vec![ bound_sig .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])) - .to_predicate(tcx), + .upcast(tcx), ]; // Additionally, we need to check that the closure kind @@ -510,7 +508,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc async_fn_kind_trait_def_id, [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ) - .to_predicate(tcx), + .upcast(tcx), ); } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 2058650f288..52deb22098f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -40,13 +40,13 @@ trait ResponseT<'tcx> { fn var_values(&self) -> CanonicalVarValues<'tcx>; } -impl<'tcx> ResponseT<'tcx> for Response<'tcx> { +impl<'tcx> ResponseT<'tcx> for Response<TyCtxt<'tcx>> { fn var_values(&self) -> CanonicalVarValues<'tcx> { self.var_values } } -impl<'tcx, T> ResponseT<'tcx> for inspect::State<'tcx, T> { +impl<'tcx, T> ResponseT<'tcx> for inspect::State<TyCtxt<'tcx>, T> { fn var_values(&self) -> CanonicalVarValues<'tcx> { self.var_values } @@ -384,7 +384,7 @@ pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>> var_values: &[ty::GenericArg<'tcx>], max_input_universe: ty::UniverseIndex, data: T, -) -> inspect::CanonicalState<'tcx, T> { +) -> inspect::CanonicalState<TyCtxt<'tcx>, T> { let var_values = CanonicalVarValues { var_values: infcx.tcx.mk_args(var_values) }; let state = inspect::State { var_values, data }; let state = state.fold_with(&mut EagerResolver::new(infcx)); @@ -414,7 +414,7 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt span: Span, param_env: ty::ParamEnv<'tcx>, orig_values: &mut Vec<ty::GenericArg<'tcx>>, - state: inspect::CanonicalState<'tcx, T>, + state: inspect::CanonicalState<TyCtxt<'tcx>, T>, ) -> T { // In case any fresh inference variables have been created between `state` // and the previous instantiation, extend `orig_values` for it. diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index e5d26e530ee..70308d4359d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,3 +1,6 @@ +use std::io::Write; +use std::ops::ControlFlow; + use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; @@ -8,13 +11,12 @@ use rustc_infer::infer::{ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals}; use rustc_infer::traits::ObligationCause; -use rustc_macros::{extension, HashStable}; +use rustc_macros::{extension, HashStable, HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_middle::bug; use rustc_middle::infer::canonical::CanonicalVarInfos; -use rustc_middle::traits::solve::inspect; use rustc_middle::traits::solve::{ - CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques, PredefinedOpaquesData, - QueryResult, + inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques, + PredefinedOpaquesData, QueryResult, }; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::{ @@ -23,8 +25,8 @@ use rustc_middle::ty::{ }; use rustc_session::config::DumpSolverProofTree; use rustc_span::DUMMY_SP; -use std::io::Write; -use std::ops::ControlFlow; +use rustc_type_ir::{self as ir, Interner}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::traits::coherence; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; @@ -85,7 +87,7 @@ pub struct EvalCtxt<'a, 'tcx> { pub(super) search_graph: &'a mut SearchGraph<'tcx>, - nested_goals: NestedGoals<'tcx>, + nested_goals: NestedGoals<TyCtxt<'tcx>>, // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`? // @@ -95,11 +97,15 @@ pub struct EvalCtxt<'a, 'tcx> { // evaluation code. tainted: Result<(), NoSolution>, - pub(super) inspect: ProofTreeBuilder<'tcx>, + pub(super) inspect: ProofTreeBuilder<TyCtxt<'tcx>>, } -#[derive(Default, Debug, Clone)] -pub(super) struct NestedGoals<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(Clone(bound = ""), Debug(bound = ""), Default(bound = ""))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[derive(TyDecodable, TyEncodable, HashStable_NoContext)] +// FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate. +pub struct NestedGoals<I: Interner> { /// These normalizes-to goals are treated specially during the evaluation /// loop. In each iteration we take the RHS of the projection, replace it with /// a fresh inference variable, and only after evaluating that goal do we @@ -110,17 +116,17 @@ pub(super) struct NestedGoals<'tcx> { /// /// Forgetting to replace the RHS with a fresh inference variable when we evaluate /// this goal results in an ICE.. - pub(super) normalizes_to_goals: Vec<Goal<'tcx, ty::NormalizesTo<'tcx>>>, + pub normalizes_to_goals: Vec<ir::solve::Goal<I, ir::NormalizesTo<I>>>, /// The rest of the goals which have not yet processed or remain ambiguous. - pub(super) goals: Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>, + pub goals: Vec<(GoalSource, ir::solve::Goal<I, I::Predicate>)>, } -impl<'tcx> NestedGoals<'tcx> { - pub(super) fn new() -> Self { +impl<I: Interner> NestedGoals<I> { + pub fn new() -> Self { Self { normalizes_to_goals: Vec::new(), goals: Vec::new() } } - pub(super) fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.normalizes_to_goals.is_empty() && self.goals.is_empty() } } @@ -143,7 +149,8 @@ impl<'tcx> InferCtxt<'tcx> { &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option<inspect::GoalEvaluation<'tcx>>) { + ) -> (Result<(bool, Certainty), NoSolution>, Option<inspect::GoalEvaluation<TyCtxt<'tcx>>>) + { EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) @@ -166,7 +173,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { infcx: &InferCtxt<'tcx>, generate_proof_tree: GenerateProofTree, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> R, - ) -> (R, Option<inspect::GoalEvaluation<'tcx>>) { + ) -> (R, Option<inspect::GoalEvaluation<TyCtxt<'tcx>>>) { let mode = if infcx.intercrate { SolverMode::Coherence } else { SolverMode::Normal }; let mut search_graph = search_graph::SearchGraph::new(mode); @@ -220,7 +227,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, search_graph: &'a mut search_graph::SearchGraph<'tcx>, canonical_input: CanonicalInput<'tcx>, - canonical_goal_evaluation: &mut ProofTreeBuilder<'tcx>, + canonical_goal_evaluation: &mut ProofTreeBuilder<TyCtxt<'tcx>>, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>, Goal<'tcx, ty::Predicate<'tcx>>) -> R, ) -> R { let intercrate = match search_graph.solver_mode() { @@ -282,7 +289,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, search_graph: &'a mut search_graph::SearchGraph<'tcx>, canonical_input: CanonicalInput<'tcx>, - goal_evaluation: &mut ProofTreeBuilder<'tcx>, + goal_evaluation: &mut ProofTreeBuilder<TyCtxt<'tcx>>, ) -> QueryResult<'tcx> { let mut canonical_goal_evaluation = goal_evaluation.new_canonical_goal_evaluation(canonical_input); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index 47109c8ad5d..9edc489754c 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -2,10 +2,9 @@ use crate::solve::assembly::Candidate; use super::EvalCtxt; use rustc_infer::traits::BuiltinImplSource; -use rustc_middle::traits::{ - query::NoSolution, - solve::{inspect, CandidateSource, QueryResult}, -}; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::{inspect, CandidateSource, QueryResult}; +use rustc_middle::ty::TyCtxt; use std::marker::PhantomData; pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> { @@ -16,7 +15,7 @@ pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> { impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T> where - F: FnOnce(&T) -> inspect::ProbeKind<'tcx>, + F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>, { pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T { let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; @@ -51,12 +50,12 @@ where pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, 'tcx, F> { cx: ProbeCtxt<'me, 'a, 'tcx, F, QueryResult<'tcx>>, - source: CandidateSource, + source: CandidateSource<'tcx>, } impl<'tcx, F> TraitProbeCtxt<'_, '_, 'tcx, F> where - F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>, + F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>, { #[instrument(level = "debug", skip_all, fields(source = ?self.source))] pub(in crate::solve) fn enter( @@ -72,7 +71,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { /// as expensive as necessary to output the desired information. pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, 'tcx, F, T> where - F: FnOnce(&T) -> inspect::ProbeKind<'tcx>, + F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>, { ProbeCtxt { ecx: self, probe_kind, _result: PhantomData } } @@ -80,16 +79,24 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { pub(in crate::solve) fn probe_builtin_trait_candidate( &mut self, source: BuiltinImplSource, - ) -> TraitProbeCtxt<'_, 'a, 'tcx, impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>> - { + ) -> TraitProbeCtxt< + '_, + 'a, + 'tcx, + impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>, + > { self.probe_trait_candidate(CandidateSource::BuiltinImpl(source)) } pub(in crate::solve) fn probe_trait_candidate( &mut self, - source: CandidateSource, - ) -> TraitProbeCtxt<'_, 'a, 'tcx, impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>> - { + source: CandidateSource<'tcx>, + ) -> TraitProbeCtxt< + '_, + 'a, + 'tcx, + impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>, + > { TraitProbeCtxt { cx: ProbeCtxt { ecx: self, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3323f1bbf39..4933080451d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -3,7 +3,6 @@ use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, @@ -15,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; use super::eval_ctxt::GenerateProofTree; -use super::inspect::{InspectCandidate, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; /// A trait engine using the new trait solver. @@ -244,16 +243,23 @@ fn fulfillment_error_for_no_solution<'tcx>( fn fulfillment_error_for_stalled<'tcx>( infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, + root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { - let code = infcx.probe(|_| { - match infcx.evaluate_root_goal(obligation.clone().into(), GenerateProofTree::Never).0 { + let (code, refine_obligation) = infcx.probe(|_| { + match infcx.evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::Never).0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { - FulfillmentErrorCode::Ambiguity { overflow: None } - } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => { - FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } + (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } + Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, + // Don't look into overflows because we treat overflows weirdly anyways. + // In `instantiate_response_discarding_overflow` we set `has_changed = false`, + // recomputing the goal again during `find_best_leaf_obligation` may apply + // inference guidance that makes other goals go from ambig -> pass, for example. + // + // FIXME: We should probably just look into overflows here. + false, + ), Ok((_, Certainty::Yes)) => { bug!("did not expect successful goal when collecting ambiguity errors") } @@ -264,9 +270,13 @@ fn fulfillment_error_for_stalled<'tcx>( }); FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &obligation, true), + obligation: if refine_obligation { + find_best_leaf_obligation(infcx, &root_obligation, true) + } else { + root_obligation.clone() + }, code, - root_obligation: obligation, + root_obligation, } } @@ -302,41 +312,50 @@ impl<'tcx> BestObligation<'tcx> { res } - /// Filter out the candidates that aren't either error or ambiguous (depending - /// on what we are looking for), and also throw out candidates that have no - /// failing WC (or higher-ranked obligations, for which there should only be - /// one candidate anyways -- but I digress). This most likely means that the - /// goal just didn't unify at all, e.g. a param candidate with an alias in it. + /// Filter out the candidates that aren't interesting to visit for the + /// purposes of reporting errors. For ambiguities, we only consider + /// candidates that may hold. For errors, we only consider candidates that + /// *don't* hold and which have impl-where clauses that also don't hold. fn non_trivial_candidates<'a>( &self, - goal: &'a InspectGoal<'a, 'tcx>, - ) -> Vec<InspectCandidate<'a, 'tcx>> { - let mut candidates = goal - .candidates() - .into_iter() - .filter(|candidate| match self.consider_ambiguities { - true => matches!(candidate.result(), Ok(Certainty::Maybe(_))), - false => matches!(candidate.result(), Err(_)), - }) - .collect::<Vec<_>>(); - - // If we have >1 candidate, one may still be due to "boring" reasons, like - // an alias-relate that failed to hold when deeply evaluated. We really - // don't care about reasons like this. - if candidates.len() > 1 { - candidates.retain(|candidate| { - goal.infcx().probe(|_| { - candidate.instantiate_nested_goals(self.span()).iter().any(|nested_goal| { - matches!( - nested_goal.source(), - GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked - ) && match self.consider_ambiguities { - true => matches!(nested_goal.result(), Ok(Certainty::Maybe(_))), - false => matches!(nested_goal.result(), Err(_)), - } - }) - }) - }); + goal: &'a inspect::InspectGoal<'a, 'tcx>, + ) -> Vec<inspect::InspectCandidate<'a, 'tcx>> { + let mut candidates = goal.candidates(); + match self.consider_ambiguities { + true => { + // If we have an ambiguous obligation, we must consider *all* candidates + // that hold, or else we may guide inference causing other goals to go + // from ambig -> pass/fail. + candidates.retain(|candidate| candidate.result().is_ok()); + } + false => { + // If we have >1 candidate, one may still be due to "boring" reasons, like + // an alias-relate that failed to hold when deeply evaluated. We really + // don't care about reasons like this. + if candidates.len() > 1 { + candidates.retain(|candidate| { + goal.infcx().probe(|_| { + candidate.instantiate_nested_goals(self.span()).iter().any( + |nested_goal| { + matches!( + nested_goal.source(), + GoalSource::ImplWhereBound + | GoalSource::InstantiateHigherRanked + ) && match self.consider_ambiguities { + true => { + matches!( + nested_goal.result(), + Ok(Certainty::Maybe(MaybeCause::Ambiguity)) + ) + } + false => matches!(nested_goal.result(), Err(_)), + } + }, + ) + }) + }); + } + } } candidates @@ -350,58 +369,88 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { self.obligation.cause.span } - fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { let candidates = self.non_trivial_candidates(goal); let [candidate] = candidates.as_slice() else { return ControlFlow::Break(self.obligation.clone()); }; // Don't walk into impls that have `do_not_recommend`. - if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } = - candidate.kind() + if let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } = candidate.kind() && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend) { return ControlFlow::Break(self.obligation.clone()); } - // FIXME: Could we extract a trait ref from a projection here too? + let tcx = goal.infcx().tcx; // FIXME: Also, what about considering >1 layer up the stack? May be necessary // for normalizes-to. - let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else { - return ControlFlow::Break(self.obligation.clone()); + let pred_kind = goal.goal().predicate.kind(); + let child_mode = match pred_kind.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => { + ChildMode::Trait(pred_kind.rebind(parent_trait_pred)) + } + ty::PredicateKind::NormalizesTo(normalizes_to) + if matches!( + normalizes_to.alias.kind(tcx), + ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst + ) => + { + ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { + trait_ref: normalizes_to.alias.trait_ref(tcx), + polarity: ty::PredicatePolarity::Positive, + })) + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => { + ChildMode::WellFormedObligation + } + _ => { + return ControlFlow::Break(self.obligation.clone()); + } }; - let tcx = goal.infcx().tcx; let mut impl_where_bound_count = 0; for nested_goal in candidate.instantiate_nested_goals(self.span()) { + let make_obligation = |cause| Obligation { + cause, + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + let obligation; - match nested_goal.source() { - GoalSource::Misc => { + match (child_mode, nested_goal.source()) { + (ChildMode::Trait(_), GoalSource::Misc) => { continue; } - GoalSource::ImplWhereBound => { - obligation = Obligation { - cause: derive_cause( - tcx, - candidate.kind(), - self.obligation.cause.clone(), - impl_where_bound_count, - parent_trait_pred, - ), - param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, - recursion_depth: self.obligation.recursion_depth + 1, - }; + (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { + obligation = make_obligation(derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + )); impl_where_bound_count += 1; } - GoalSource::InstantiateHigherRanked => { + // Skip over a higher-ranked predicate. + (_, GoalSource::InstantiateHigherRanked) => { obligation = self.obligation.clone(); } + (ChildMode::WellFormedObligation, _) => { + obligation = make_obligation(self.obligation.cause.clone()); + } } // Skip nested goals that aren't the *reason* for our goal's failure. match self.consider_ambiguities { - true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {} + true if matches!( + nested_goal.result(), + Ok(Certainty::Maybe(MaybeCause::Ambiguity)) + ) => {} false if matches!(nested_goal.result(), Err(_)) => {} _ => continue, } @@ -413,15 +462,30 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } } +#[derive(Copy, Clone)] +enum ChildMode<'tcx> { + // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, + // and skip all `GoalSource::Misc`, which represent useless obligations + // such as alias-eq which may not hold. + Trait(ty::PolyTraitPredicate<'tcx>), + // Skip trying to derive an `ObligationCause` from this obligation, and + // report *all* sub-obligations as if they came directly from the parent + // obligation. + WellFormedObligation, +} + fn derive_cause<'tcx>( tcx: TyCtxt<'tcx>, - candidate_kind: ProbeKind<'tcx>, + candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>, mut cause: ObligationCause<'tcx>, idx: usize, parent_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> ObligationCause<'tcx> { match candidate_kind { - ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } => { if let Some((_, span)) = tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) { @@ -435,7 +499,10 @@ fn derive_cause<'tcx>( }) } } - ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::BuiltinImpl(..), + result: _, + } => { cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived); } _ => {} diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index b71a1b339cb..e12c66b6928 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -18,7 +18,7 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::{TyCtxt, TypeFoldable}; use rustc_middle::{bug, ty}; use rustc_span::{Span, DUMMY_SP}; @@ -37,7 +37,7 @@ pub struct InspectGoal<'a, 'tcx> { orig_values: Vec<ty::GenericArg<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>, result: Result<Certainty, NoSolution>, - evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>, + evaluation_kind: inspect::CanonicalGoalEvaluationKind<TyCtxt<'tcx>>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, source: GoalSource, } @@ -88,16 +88,17 @@ impl<'tcx> NormalizesToTermHack<'tcx> { pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, - kind: inspect::ProbeKind<'tcx>, - nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>, - final_state: inspect::CanonicalState<'tcx, ()>, - impl_args: Option<inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>>>, + kind: inspect::ProbeKind<TyCtxt<'tcx>>, + nested_goals: + Vec<(GoalSource, inspect::CanonicalState<TyCtxt<'tcx>, Goal<'tcx, ty::Predicate<'tcx>>>)>, + final_state: inspect::CanonicalState<TyCtxt<'tcx>, ()>, + impl_args: Option<inspect::CanonicalState<TyCtxt<'tcx>, ty::GenericArgsRef<'tcx>>>, result: QueryResult<'tcx>, shallow_certainty: Certainty, } impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { - pub fn kind(&self) -> inspect::ProbeKind<'tcx> { + pub fn kind(&self) -> inspect::ProbeKind<TyCtxt<'tcx>> { self.kind } @@ -280,9 +281,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { candidates: &mut Vec<InspectCandidate<'a, 'tcx>>, nested_goals: &mut Vec<( GoalSource, - inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>, + inspect::CanonicalState<TyCtxt<'tcx>, Goal<'tcx, ty::Predicate<'tcx>>>, )>, - probe: &inspect::Probe<'tcx>, + probe: &inspect::Probe<TyCtxt<'tcx>>, ) { let mut shallow_certainty = None; let mut impl_args = None; @@ -387,7 +388,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { fn new( infcx: &'a InferCtxt<'tcx>, depth: usize, - root: inspect::GoalEvaluation<'tcx>, + root: inspect::GoalEvaluation<TyCtxt<'tcx>>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, source: GoalSource, ) -> Self { diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 9dd681f09e7..803300c5196 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -9,11 +9,12 @@ use rustc_infer::infer::InferCtxt; use rustc_middle::bug; use rustc_middle::infer::canonical::CanonicalVarValues; use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::solve::{ +use rustc_middle::ty::{self, TyCtxt}; +use rustc_next_trait_solver::solve::{ CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; -use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::DumpSolverProofTree; +use rustc_type_ir::Interner; use crate::solve::eval_ctxt::canonical; use crate::solve::{self, inspect, GenerateProofTree}; @@ -38,49 +39,51 @@ use crate::solve::{self, inspect, GenerateProofTree}; /// trees. At the end of trait solving `ProofTreeBuilder::finalize` /// is called to recursively convert the whole structure to a /// finished proof tree. -pub(in crate::solve) struct ProofTreeBuilder<'tcx> { - state: Option<Box<DebugSolver<'tcx>>>, +pub(in crate::solve) struct ProofTreeBuilder<I: Interner> { + state: Option<Box<DebugSolver<I>>>, } /// The current state of the proof tree builder, at most places /// in the code, only one or two variants are actually possible. /// /// We simply ICE in case that assumption is broken. -#[derive(Debug)] -enum DebugSolver<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(Debug(bound = ""))] +enum DebugSolver<I: Interner> { Root, - GoalEvaluation(WipGoalEvaluation<'tcx>), - CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<'tcx>), - GoalEvaluationStep(WipGoalEvaluationStep<'tcx>), + GoalEvaluation(WipGoalEvaluation<I>), + CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<I>), + GoalEvaluationStep(WipGoalEvaluationStep<I>), } -impl<'tcx> From<WipGoalEvaluation<'tcx>> for DebugSolver<'tcx> { - fn from(g: WipGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { +impl<I: Interner> From<WipGoalEvaluation<I>> for DebugSolver<I> { + fn from(g: WipGoalEvaluation<I>) -> DebugSolver<I> { DebugSolver::GoalEvaluation(g) } } -impl<'tcx> From<WipCanonicalGoalEvaluation<'tcx>> for DebugSolver<'tcx> { - fn from(g: WipCanonicalGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { +impl<I: Interner> From<WipCanonicalGoalEvaluation<I>> for DebugSolver<I> { + fn from(g: WipCanonicalGoalEvaluation<I>) -> DebugSolver<I> { DebugSolver::CanonicalGoalEvaluation(g) } } -impl<'tcx> From<WipGoalEvaluationStep<'tcx>> for DebugSolver<'tcx> { - fn from(g: WipGoalEvaluationStep<'tcx>) -> DebugSolver<'tcx> { +impl<I: Interner> From<WipGoalEvaluationStep<I>> for DebugSolver<I> { + fn from(g: WipGoalEvaluationStep<I>) -> DebugSolver<I> { DebugSolver::GoalEvaluationStep(g) } } -#[derive(Eq, PartialEq, Debug)] -struct WipGoalEvaluation<'tcx> { - pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, - pub kind: WipGoalEvaluationKind<'tcx>, - pub evaluation: Option<WipCanonicalGoalEvaluation<'tcx>>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +struct WipGoalEvaluation<I: Interner> { + pub uncanonicalized_goal: Goal<I, I::Predicate>, + pub kind: WipGoalEvaluationKind<I>, + pub evaluation: Option<WipCanonicalGoalEvaluation<I>>, } -impl<'tcx> WipGoalEvaluation<'tcx> { - fn finalize(self) -> inspect::GoalEvaluation<'tcx> { +impl<I: Interner> WipGoalEvaluation<I> { + fn finalize(self) -> inspect::GoalEvaluation<I> { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, kind: match self.kind { @@ -94,21 +97,23 @@ impl<'tcx> WipGoalEvaluation<'tcx> { } } -#[derive(Eq, PartialEq, Debug)] -pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> { - Root { orig_values: Vec<ty::GenericArg<'tcx>> }, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +pub(in crate::solve) enum WipGoalEvaluationKind<I: Interner> { + Root { orig_values: Vec<I::GenericArg> }, Nested, } -#[derive(Eq, PartialEq)] -pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""))] +pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<I: Interner> { Overflow, CycleInStack, ProvisionalCacheHit, - Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] }, + Interned { revisions: I::GoalEvaluationSteps }, } -impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> { +impl<I: Interner> std::fmt::Debug for WipCanonicalGoalEvaluationKind<I> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Overflow => write!(f, "Overflow"), @@ -119,18 +124,19 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> { } } -#[derive(Eq, PartialEq, Debug)] -struct WipCanonicalGoalEvaluation<'tcx> { - goal: CanonicalInput<'tcx>, - kind: Option<WipCanonicalGoalEvaluationKind<'tcx>>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +struct WipCanonicalGoalEvaluation<I: Interner> { + goal: CanonicalInput<I>, + kind: Option<WipCanonicalGoalEvaluationKind<I>>, /// Only used for uncached goals. After we finished evaluating /// the goal, this is interned and moved into `kind`. - revisions: Vec<WipGoalEvaluationStep<'tcx>>, - result: Option<QueryResult<'tcx>>, + revisions: Vec<WipGoalEvaluationStep<I>>, + result: Option<QueryResult<I>>, } -impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { - fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> { +impl<I: Interner> WipCanonicalGoalEvaluation<I> { + fn finalize(self) -> inspect::CanonicalGoalEvaluation<I> { assert!(self.revisions.is_empty()); let kind = match self.kind.unwrap() { WipCanonicalGoalEvaluationKind::Overflow => { @@ -151,14 +157,15 @@ impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { } } -#[derive(Eq, PartialEq, Debug)] -struct WipAddedGoalsEvaluation<'tcx> { - evaluations: Vec<Vec<WipGoalEvaluation<'tcx>>>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +struct WipAddedGoalsEvaluation<I: Interner> { + evaluations: Vec<Vec<WipGoalEvaluation<I>>>, result: Option<Result<Certainty, NoSolution>>, } -impl<'tcx> WipAddedGoalsEvaluation<'tcx> { - fn finalize(self) -> inspect::AddedGoalsEvaluation<'tcx> { +impl<I: Interner> WipAddedGoalsEvaluation<I> { + fn finalize(self) -> inspect::AddedGoalsEvaluation<I> { inspect::AddedGoalsEvaluation { evaluations: self .evaluations @@ -172,22 +179,23 @@ impl<'tcx> WipAddedGoalsEvaluation<'tcx> { } } -#[derive(Eq, PartialEq, Debug)] -struct WipGoalEvaluationStep<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +struct WipGoalEvaluationStep<I: Interner> { /// Unlike `EvalCtxt::var_values`, we append a new /// generic arg here whenever we create a new inference /// variable. /// /// This is necessary as we otherwise don't unify these /// vars when instantiating multiple `CanonicalState`. - var_values: Vec<ty::GenericArg<'tcx>>, - instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, + var_values: Vec<I::GenericArg>, + instantiated_goal: QueryInput<I, I::Predicate>, probe_depth: usize, - evaluation: WipProbe<'tcx>, + evaluation: WipProbe<I>, } -impl<'tcx> WipGoalEvaluationStep<'tcx> { - fn current_evaluation_scope(&mut self) -> &mut WipProbe<'tcx> { +impl<I: Interner> WipGoalEvaluationStep<I> { + fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> { let mut current = &mut self.evaluation; for _ in 0..self.probe_depth { match current.steps.last_mut() { @@ -198,7 +206,7 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> { current } - fn added_goals_evaluation(&mut self) -> &mut WipAddedGoalsEvaluation<'tcx> { + fn added_goals_evaluation(&mut self) -> &mut WipAddedGoalsEvaluation<I> { let mut current = &mut self.evaluation; loop { match current.steps.last_mut() { @@ -209,7 +217,7 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> { } } - fn finalize(self) -> inspect::GoalEvaluationStep<'tcx> { + fn finalize(self) -> inspect::GoalEvaluationStep<I> { let evaluation = self.evaluation.finalize(); match evaluation.kind { inspect::ProbeKind::Root { .. } => (), @@ -219,16 +227,17 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> { } } -#[derive(Eq, PartialEq, Debug)] -struct WipProbe<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +struct WipProbe<I: Interner> { initial_num_var_values: usize, - steps: Vec<WipProbeStep<'tcx>>, - kind: Option<inspect::ProbeKind<'tcx>>, - final_state: Option<inspect::CanonicalState<'tcx, ()>>, + steps: Vec<WipProbeStep<I>>, + kind: Option<inspect::ProbeKind<I>>, + final_state: Option<inspect::CanonicalState<I, ()>>, } -impl<'tcx> WipProbe<'tcx> { - fn finalize(self) -> inspect::Probe<'tcx> { +impl<I: Interner> WipProbe<I> { + fn finalize(self) -> inspect::Probe<I> { inspect::Probe { steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(), kind: self.kind.unwrap(), @@ -237,17 +246,18 @@ impl<'tcx> WipProbe<'tcx> { } } -#[derive(Eq, PartialEq, Debug)] -enum WipProbeStep<'tcx> { - AddGoal(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>), - EvaluateGoals(WipAddedGoalsEvaluation<'tcx>), - NestedProbe(WipProbe<'tcx>), +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +enum WipProbeStep<I: Interner> { + AddGoal(GoalSource, inspect::CanonicalState<I, Goal<I, I::Predicate>>), + EvaluateGoals(WipAddedGoalsEvaluation<I>), + NestedProbe(WipProbe<I>), MakeCanonicalResponse { shallow_certainty: Certainty }, - RecordImplArgs { impl_args: inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> }, + RecordImplArgs { impl_args: inspect::CanonicalState<I, I::GenericArgs> }, } -impl<'tcx> WipProbeStep<'tcx> { - fn finalize(self) -> inspect::ProbeStep<'tcx> { +impl<I: Interner> WipProbeStep<I> { + fn finalize(self) -> inspect::ProbeStep<I> { match self { WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal), WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), @@ -262,26 +272,27 @@ impl<'tcx> WipProbeStep<'tcx> { } } -impl<'tcx> ProofTreeBuilder<'tcx> { - fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> { +// FIXME: Genericize this impl. +impl<'tcx> ProofTreeBuilder<TyCtxt<'tcx>> { + fn new(state: impl Into<DebugSolver<TyCtxt<'tcx>>>) -> ProofTreeBuilder<TyCtxt<'tcx>> { ProofTreeBuilder { state: Some(Box::new(state.into())) } } - fn nested<T: Into<DebugSolver<'tcx>>>(&self, state: impl FnOnce() -> T) -> Self { + fn nested<T: Into<DebugSolver<TyCtxt<'tcx>>>>(&self, state: impl FnOnce() -> T) -> Self { ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) } } - fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> { + fn as_mut(&mut self) -> Option<&mut DebugSolver<TyCtxt<'tcx>>> { self.state.as_deref_mut() } - pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<'tcx> { + pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<TyCtxt<'tcx>> { let mut nested = ProofTreeBuilder { state: self.state.take() }; nested.enter_probe(); nested } - pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> { + pub fn finalize(self) -> Option<inspect::GoalEvaluation<TyCtxt<'tcx>>> { match *self.state? { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) @@ -293,7 +304,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_maybe_root( tcx: TyCtxt<'tcx>, generate_proof_tree: GenerateProofTree, - ) -> ProofTreeBuilder<'tcx> { + ) -> ProofTreeBuilder<TyCtxt<'tcx>> { match generate_proof_tree { GenerateProofTree::Never => ProofTreeBuilder::new_noop(), GenerateProofTree::IfEnabled => { @@ -311,11 +322,11 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn new_root() -> ProofTreeBuilder<'tcx> { + pub fn new_root() -> ProofTreeBuilder<TyCtxt<'tcx>> { ProofTreeBuilder::new(DebugSolver::Root) } - pub fn new_noop() -> ProofTreeBuilder<'tcx> { + pub fn new_noop() -> ProofTreeBuilder<TyCtxt<'tcx>> { ProofTreeBuilder { state: None } } @@ -325,10 +336,10 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub(in crate::solve) fn new_goal_evaluation( &mut self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, + goal: Goal<TyCtxt<'tcx>, ty::Predicate<'tcx>>, orig_values: &[ty::GenericArg<'tcx>], kind: solve::GoalEvaluationKind, - ) -> ProofTreeBuilder<'tcx> { + ) -> ProofTreeBuilder<TyCtxt<'tcx>> { self.nested(|| WipGoalEvaluation { uncanonicalized_goal: goal, kind: match kind { @@ -343,8 +354,8 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_canonical_goal_evaluation( &mut self, - goal: CanonicalInput<'tcx>, - ) -> ProofTreeBuilder<'tcx> { + goal: CanonicalInput<TyCtxt<'tcx>>, + ) -> ProofTreeBuilder<TyCtxt<'tcx>> { self.nested(|| WipCanonicalGoalEvaluation { goal, kind: None, @@ -356,7 +367,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn finalize_evaluation( &mut self, tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]> { + ) -> Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]> { self.as_mut().map(|this| match this { DebugSolver::CanonicalGoalEvaluation(evaluation) => { let revisions = mem::take(&mut evaluation.revisions) @@ -371,7 +382,10 @@ impl<'tcx> ProofTreeBuilder<'tcx> { }) } - pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) { + pub fn canonical_goal_evaluation( + &mut self, + canonical_goal_evaluation: ProofTreeBuilder<TyCtxt<'tcx>>, + ) { if let Some(this) = self.as_mut() { match (this, *canonical_goal_evaluation.state.unwrap()) { ( @@ -386,7 +400,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<'tcx>) { + pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<TyCtxt<'tcx>>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -397,7 +411,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) { + pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<TyCtxt<'tcx>>) { if let Some(this) = self.as_mut() { match (this, *goal_evaluation.state.unwrap()) { ( @@ -418,8 +432,8 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_goal_evaluation_step( &mut self, var_values: CanonicalVarValues<'tcx>, - instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, - ) -> ProofTreeBuilder<'tcx> { + instantiated_goal: QueryInput<TyCtxt<'tcx>, ty::Predicate<'tcx>>, + ) -> ProofTreeBuilder<TyCtxt<'tcx>> { self.nested(|| WipGoalEvaluationStep { var_values: var_values.var_values.to_vec(), instantiated_goal, @@ -433,7 +447,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { }) } - pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) { + pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<TyCtxt<'tcx>>) { if let Some(this) = self.as_mut() { match (this, *goal_evaluation_step.state.unwrap()) { ( @@ -474,7 +488,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<'tcx>) { + pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<TyCtxt<'tcx>>) { match self.as_mut() { None => {} Some(DebugSolver::GoalEvaluationStep(state)) => { @@ -510,7 +524,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { &mut self, infcx: &InferCtxt<'tcx>, max_input_universe: ty::UniverseIndex, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, + goal: Goal<TyCtxt<'tcx>, ty::NormalizesTo<'tcx>>, ) { self.add_goal( infcx, @@ -525,7 +539,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { infcx: &InferCtxt<'tcx>, max_input_universe: ty::UniverseIndex, source: GoalSource, - goal: Goal<'tcx, ty::Predicate<'tcx>>, + goal: Goal<TyCtxt<'tcx>, ty::Predicate<'tcx>>, ) { match self.as_mut() { None => {} @@ -579,7 +593,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn finish_probe(mut self) -> ProofTreeBuilder<'tcx> { + pub fn finish_probe(mut self) -> ProofTreeBuilder<TyCtxt<'tcx>> { match self.as_mut() { None => {} Some(DebugSolver::GoalEvaluationStep(state)) => { @@ -627,7 +641,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn query_result(&mut self, result: QueryResult<'tcx>) { + pub fn query_result(&mut self, result: QueryResult<TyCtxt<'tcx>>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 6c912db975a..b085d009d75 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -22,9 +22,9 @@ use rustc_middle::infer::canonical::CanonicalVarInfos; use rustc_middle::traits::solve::{ CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, QueryResult, Response, }; -use rustc_middle::ty::{self, AliasRelationDirection, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{ - CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate, + self, AliasRelationDirection, CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, Ty, + TyCtxt, TypeOutlivesPredicate, UniverseIndex, }; mod alias_relate; @@ -74,7 +74,7 @@ enum GoalEvaluationKind { } #[extension(trait CanonicalResponseExt)] -impl<'tcx> Canonical<'tcx, Response<'tcx>> { +impl<'tcx> Canonical<'tcx, Response<TyCtxt<'tcx>>> { fn has_no_inference_or_external_constraints(&self) -> bool { self.value.external_constraints.region_constraints.is_empty() && self.value.var_values.is_identity() diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 6ec0ad9d29a..8c492b62c1a 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -3,7 +3,6 @@ use crate::traits::specialization_graph; use super::assembly::structural_traits::AsyncCallableRelevantTypes; use super::assembly::{self, structural_traits, Candidate}; use super::{EvalCtxt, GoalSource}; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_infer::traits::query::NoSolution; @@ -16,7 +15,7 @@ use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::NormalizesTo; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; +use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; @@ -54,23 +53,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, goal: Goal<'tcx, NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { - let def_id = goal.predicate.def_id(); - match self.tcx().def_kind(def_id) { - DefKind::AssocTy | DefKind::AssocConst => { - match self.tcx().associated_item(def_id).container { - ty::AssocItemContainer::TraitContainer => { - let candidates = self.assemble_and_evaluate_candidates(goal); - self.merge_candidates(candidates) - } - ty::AssocItemContainer::ImplContainer => { - self.normalize_inherent_associated_type(goal) - } - } + match goal.predicate.alias.kind(self.tcx()) { + ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { + let candidates = self.assemble_and_evaluate_candidates(goal); + self.merge_candidates(candidates) } - DefKind::AnonConst => self.normalize_anon_const(goal), - DefKind::TyAlias => self.normalize_weak_type(goal), - DefKind::OpaqueTy => self.normalize_opaque_type(goal), - kind => bug!("unknown DefKind {} in normalizes-to goal: {goal:#?}", kind.descr(def_id)), + ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal), + ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal), + ty::AliasTermKind::WeakTy => self.normalize_weak_type(goal), + ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal), } } @@ -108,7 +99,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + source: CandidateSource<'tcx>, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, @@ -370,7 +361,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), term: output.into(), }) - .to_predicate(tcx); + .upcast(tcx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -452,7 +443,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::ProjectionPredicate { projection_term, term } }, ) - .to_predicate(tcx); + .upcast(tcx); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -629,7 +620,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } - .to_predicate(tcx), + .upcast(tcx), // Technically, we need to check that the future type is Sized, // but that's already proven by the coroutine being WF. [], @@ -661,7 +652,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } - .to_predicate(tcx), + .upcast(tcx), // Technically, we need to check that the iterator type is Sized, // but that's already proven by the generator being WF. [], @@ -749,7 +740,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), term, } - .to_predicate(tcx), + .upcast(tcx), // Technically, we need to check that the coroutine type is Sized, // but that's already proven by the coroutine being WF. [], diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index 60362aa01da..0164d44667c 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -253,8 +253,8 @@ impl<'tcx> SearchGraph<'tcx> { &mut self, tcx: TyCtxt<'tcx>, input: CanonicalInput<'tcx>, - inspect: &mut ProofTreeBuilder<'tcx>, - mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<'tcx>) -> QueryResult<'tcx>, + inspect: &mut ProofTreeBuilder<TyCtxt<'tcx>>, + mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<TyCtxt<'tcx>>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { // Check for overflow. let Some(available_depth) = Self::allowed_depth_for_nested(tcx, &self.stack) else { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 1cafa970b68..9139c75d399 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -15,7 +15,7 @@ use rustc_middle::traits::solve::inspect::ProbeKind; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::{BuiltinImplSource, Reveal}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; @@ -103,7 +103,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + source: CandidateSource<'tcx>, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, @@ -315,7 +315,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .map_bound(|(inputs, _)| { ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) }) - .to_predicate(tcx); + .upcast(tcx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) Self::probe_and_consider_implied_clause( @@ -363,7 +363,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { [goal.predicate.self_ty(), tupled_inputs_ty], ) }) - .to_predicate(tcx); + .upcast(tcx); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) Self::probe_and_consider_implied_clause( @@ -560,7 +560,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()]) - .to_predicate(tcx), + .upcast(tcx), // Technically, we need to check that the coroutine types are Sized, // but that's already proven by the coroutine being WF. [], @@ -821,7 +821,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn consider_builtin_upcast_to_principal( &mut self, goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - source: CandidateSource, + source: CandidateSource<'tcx>, a_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, a_region: ty::Region<'tcx>, b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, @@ -1149,7 +1149,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// wrapped in one. fn probe_and_evaluate_goal_for_constituent_tys( &mut self, - source: CandidateSource, + source: CandidateSource<'tcx>, goal: Goal<'tcx, TraitPredicate<'tcx>>, constituent_tys: impl Fn( &EvalCtxt<'_, 'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 60562acfe93..1ea207cc375 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -303,7 +303,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { Err(SelectionError::Unimplemented) => { if self.is_param_no_infer(pred.skip_binder().trait_ref.args) { already_visited.remove(&pred); - self.add_user_pred(&mut user_computed_preds, pred.to_predicate(self.tcx)); + self.add_user_pred(&mut user_computed_preds, pred.upcast(self.tcx)); predicates.push_back(pred); } else { debug!( diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 551c8e7702e..4684c7171d8 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -25,8 +25,8 @@ use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::Upcast; use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -96,7 +96,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), + predicate: trait_ref.upcast(tcx), }); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 7fc94b31b3b..32c8a454b40 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -205,9 +205,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if self_ty.is_fn() { let fn_sig = self_ty.fn_sig(self.tcx); - let shortname = match fn_sig.unsafety() { - hir::Unsafety::Normal => "fn", - hir::Unsafety::Unsafe => "unsafe fn", + let shortname = match fn_sig.safety() { + hir::Safety::Safe => "fn", + hir::Safety::Unsafe => "unsafe fn", }; flags.push((sym::_Self, Some(shortname.to_owned()))); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 86610855441..f9b6b281f92 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -31,8 +31,8 @@ use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs, - InferTy, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, TypeckResults, + InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, TypeckResults, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; @@ -192,7 +192,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( }, // `fn foo(t: impl Trait)` // ^ suggest `where <T as Trait>::A: Bound` - predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)), + predicate_constraint(hir_generics, trait_pred.upcast(tcx)), ]; sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string()))); @@ -215,7 +215,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })), super_traits, ) { - (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)), + (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)), (None, Some((ident, []))) => ( ident.span.shrink_to_hi(), format!(": {}", trait_pred.print_modifiers_and_trait_path()), @@ -1897,7 +1897,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { *inputs, infcx.next_ty_var(DUMMY_SP), false, - hir::Unsafety::Normal, + hir::Safety::Safe, abi::Abi::Rust, ) } @@ -1905,7 +1905,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { [inputs], infcx.next_ty_var(DUMMY_SP), false, - hir::Unsafety::Normal, + hir::Safety::Safe, abi::Abi::Rust, ), }; @@ -2703,12 +2703,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { obligated_types: &mut Vec<Ty<'tcx>>, seen_requirements: &mut FxHashSet<DefId>, ) where - T: ToPredicate<'tcx>, + T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>, { let mut long_ty_file = None; let tcx = self.tcx; - let predicate = predicate.to_predicate(tcx); + let predicate = predicate.upcast(tcx); match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } @@ -2739,7 +2739,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ReferenceOutlivesReferent(..) | ObligationCauseCode::ObjectTypeBound(..) => {} ObligationCauseCode::RustCall => { - if let Some(pred) = predicate.to_opt_poly_trait_pred() + if let Some(pred) = predicate.as_trait_clause() && Some(pred.def_id()) == tcx.lang_items().sized_trait() { err.note("argument required to be sized due to `extern \"rust-call\"` ABI"); @@ -3378,7 +3378,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { break; } data = derived; - parent_predicate = child_trait_ref.to_predicate(tcx); + parent_predicate = child_trait_ref.upcast(tcx); parent_trait_pred = child_trait_ref; } } @@ -3392,7 +3392,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } count += 1; data = &child.derived; - parent_predicate = child_trait_pred.to_predicate(tcx); + parent_predicate = child_trait_pred.upcast(tcx); parent_trait_pred = child_trait_pred; } if count > 0 { @@ -3725,7 +3725,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id) - && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() + && let Some(failed_pred) = failed_pred.as_trait_clause() && let pred = failed_pred.map_bound(|pred| pred.with_self_ty(tcx, ty)) && self.predicate_must_hold_modulo_regions(&Obligation::misc( tcx, expr.span, body_id, param_env, pred, @@ -3816,7 +3816,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let Some(where_pred) = where_clauses.predicates.get(*idx) { if let Some(where_pred) = where_pred.as_trait_clause() - && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() + && let Some(failed_pred) = failed_pred.as_trait_clause() { self.enter_forall(where_pred, |where_pred| { let failed_pred = self.instantiate_binder_with_fresh_vars( @@ -3842,7 +3842,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }) } else if let Some(where_pred) = where_pred.as_projection_clause() - && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() + && let Some(failed_pred) = failed_pred.as_projection_clause() && let Some(found) = failed_pred.skip_binder().term.ty() { type_diffs = vec![Sorts(ty::error::ExpectedFound { @@ -3925,7 +3925,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let fn_sig @ ty::FnSig { abi: abi::Abi::Rust, c_variadic: false, - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, .. } = fn_ty.fn_sig(tcx).skip_binder() diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index f9824acdae0..d693bac90dc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -42,8 +42,8 @@ use rustc_middle::ty::print::{ PrintTraitRefExt as _, }; use rustc_middle::ty::{ - self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, - TypeVisitable, TypeVisitableExt, + self, SubtypePredicate, ToPolyTraitRef, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitable, + TypeVisitableExt, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::config::DumpSolverProofTree; @@ -302,9 +302,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { suggest_increasing_limit: bool, ) -> ! where - T: ToPredicate<'tcx> + Clone, + T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone, { - let predicate = obligation.predicate.clone().to_predicate(self.tcx); + let predicate = obligation.predicate.clone().upcast(self.tcx); let predicate = self.resolve_vars_if_possible(predicate); self.report_overflow_error( OverflowCause::TraitSolver(predicate), @@ -1417,7 +1417,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let mut code = obligation.cause.code(); - let mut pred = obligation.predicate.to_opt_poly_trait_pred(); + let mut pred = obligation.predicate.as_trait_clause(); while let Some((next_code, next_pred)) = code.parent() { if let Some(pred) = pred { self.enter_forall(pred, |pred| { @@ -1481,16 +1481,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return true; } - if let Some(error) = error.to_opt_poly_trait_pred() { + if let Some(error) = error.as_trait_clause() { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond)) - .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .filter_map(|implied| implied.as_trait_clause()) .any(|implied| self.can_match_trait(error, implied)) }) - } else if let Some(error) = error.to_opt_poly_projection_pred() { + } else if let Some(error) = error.as_projection_clause() { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond)) - .filter_map(|implied| implied.to_opt_poly_projection_pred()) + .filter_map(|implied| implied.as_projection_clause()) .any(|implied| self.can_match_projection(error, implied)) }) } else { @@ -2415,8 +2415,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return e; } err.note(format!("cannot satisfy `{predicate}`")); - let impl_candidates = self - .find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap()); + let impl_candidates = + self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap()); if impl_candidates.len() < 40 { self.report_similar_impl_candidates( impl_candidates.as_slice(), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 61f47bc1f23..204bb487c86 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -34,7 +34,7 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -142,7 +142,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( fn pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - pred: impl ToPredicate<'tcx>, + pred: impl Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>, ) -> bool { let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred); @@ -457,7 +457,7 @@ fn instantiate_and_check_impossible_predicates<'tcx>( // associated items. if let Some(trait_def_id) = tcx.trait_of_item(key.0) { let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, key.1); - predicates.push(ty::Binder::dummy(trait_ref).to_predicate(tcx)); + predicates.push(trait_ref.upcast(tcx)); } predicates.retain(|predicate| !predicate.has_param()); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 41080b3d9d3..abb19c7efd8 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitor, }; use rustc_middle::ty::{GenericArg, GenericArgs}; -use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; +use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -649,11 +649,11 @@ fn object_ty_for_trait<'tcx>( )); debug!(?trait_predicate); - let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx); + let pred: ty::Predicate<'tcx> = trait_ref.upcast(tcx); let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred]) .filter_map(|pred| { debug!(?pred); - let pred = pred.to_opt_poly_projection_pred()?; + let pred = pred.as_projection_clause()?; Some(pred.map_bound(|p| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty( tcx, p, @@ -752,8 +752,7 @@ fn receiver_is_dispatchable<'tcx>( // Self: Unsize<U> let unsize_predicate = - ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]) - .to_predicate(tcx); + ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx); // U: Trait<Arg1, ..., ArgN> let trait_predicate = { @@ -762,7 +761,7 @@ fn receiver_is_dispatchable<'tcx>( if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) } }); - ty::TraitRef::new(tcx, trait_def_id, args).to_predicate(tcx) + ty::TraitRef::new(tcx, trait_def_id, args).upcast(tcx) }; let caller_bounds = diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2e7d2790dc3..77ac4be35ea 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -35,7 +35,7 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast}; use rustc_span::symbol::sym; pub use rustc_middle::traits::Reveal; @@ -538,7 +538,7 @@ fn normalize_to_error<'a, 'tcx>( cause, recursion_depth: depth, param_env, - predicate: trait_ref.to_predicate(selcx.tcx()), + predicate: trait_ref.upcast(selcx.tcx()), }; Normalized { value: new_value, obligations: vec![trait_obligation] } } @@ -877,7 +877,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( let env_predicates = data .projection_bounds() .filter(|bound| bound.item_def_id() == obligation.predicate.def_id) - .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx)); + .map(|p| p.with_self_ty(tcx, object_ty).upcast(tcx)); assemble_candidates_from_predicates( selcx, @@ -1712,7 +1712,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( [sig.tupled_inputs_ty], output_ty, sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 24c6951a014..65048ffdfba 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -14,8 +14,8 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, - TraitPredicate, Ty, TyCtxt, + self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TraitPredicate, Ty, + TyCtxt, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; @@ -676,7 +676,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let assoc_ty_args = tcx.mk_args(&args); let bound = bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args); - ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx) + ty::Binder::bind_with_vars(bound, bound_vars).upcast(tcx) }; let normalized_bound = normalize_with_depth_to( self, @@ -1253,13 +1253,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span)), [source], ); - nested.push(predicate_to_obligation(tr.to_predicate(tcx))); + nested.push(predicate_to_obligation(tr.upcast(tcx))); // If the type is `Foo + 'a`, ensure that the type // being cast to `Foo + 'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); nested.push(predicate_to_obligation( - ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx), + ty::ClauseKind::TypeOutlives(outlives).upcast(tcx), )); ImplSource::Builtin(BuiltinImplSource::Misc, nested) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5b25c62689f..19affac7970 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -45,7 +45,7 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, PolyProjectionPredicate, ToPredicate}; +use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Symbol; @@ -739,8 +739,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // stack would be `T: Auto`. let cycle = stack.iter().take_while(|s| s.depth > stack_arg.1); let tcx = self.tcx(); - let cycle = - cycle.map(|stack| stack.obligation.predicate.to_predicate(tcx)); + let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx)); if self.coinductive_match(cycle) { stack.update_reached_depth(stack_arg.1); return Ok(EvaluatedToOk); @@ -1174,7 +1173,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // if the regions match exactly. let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth); let tcx = self.tcx(); - let cycle = cycle.map(|stack| stack.obligation.predicate.to_predicate(tcx)); + let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx)); if self.coinductive_match(cycle) { debug!("evaluate_stack --> recursive, coinductive"); Some(EvaluatedToOk) @@ -1379,7 +1378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { error_obligation: &Obligation<'tcx, T>, ) -> Result<(), OverflowError> where - T: ToPredicate<'tcx> + Clone, + T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone, { if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { match self.query_mode { @@ -1408,7 +1407,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { error_obligation: &Obligation<'tcx, V>, ) -> Result<(), OverflowError> where - V: ToPredicate<'tcx> + Clone, + V: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone, { self.check_recursion_depth(obligation.recursion_depth, error_obligation) } @@ -1779,9 +1778,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If this type is a GAT, and of the GAT args resolve to something new, // that means that we must have newly inferred something about the GAT. // We should give up in that case. + // FIXME(generic-associated-types): This only detects one layer of inference, + // which is probably not what we actually want, but fixing it causes some ambiguity: + // <https://github.com/rust-lang/rust/issues/125196>. if !generics.own_params.is_empty() && obligation.predicate.args[generics.parent_count..].iter().any(|&p| { - p.has_non_region_infer() && self.infcx.resolve_vars_if_possible(p) != p + p.has_non_region_infer() + && match p.unpack() { + ty::GenericArgKind::Const(ct) => { + self.infcx.shallow_resolve_const(ct) != ct + } + ty::GenericArgKind::Type(ty) => self.infcx.shallow_resolve(ty) != ty, + ty::GenericArgKind::Lifetime(_) => false, + } }) { ProjectionMatchesProjection::Ambiguous diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 83edddb9a96..445fa1761b9 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{InferCtxt, InferOk}; use rustc_middle::bug; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt, Upcast}; use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -105,7 +105,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.tcx; let trait_ref = item.trait_ref(); - let pred = trait_ref.to_predicate(tcx); + let pred = trait_ref.upcast(tcx); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); @@ -122,7 +122,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { .iter() .rev() .skip(1) - .any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred) + .any(|&(tr, _)| anonymize_predicate(tcx, tr.upcast(tcx)) == anon_pred) { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 8fd9889b4ea..c93ec43944a 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -9,7 +9,7 @@ use rustc_middle::query::Providers; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::GenericArgs; -use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry}; +use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt, Upcast, VtblEntry}; use rustc_span::{sym, Span}; use smallvec::{smallvec, SmallVec}; @@ -87,7 +87,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( let mut emit_vptr_on_new_entry = false; let mut visited = PredicateSet::new(tcx); - let predicate = trait_ref.to_predicate(tcx); + let predicate = trait_ref.upcast(tcx); let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> = smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))]; visited.insert(predicate); @@ -130,7 +130,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( // Find an unvisited supertrait match direct_super_traits_iter - .find(|&super_trait| visited.insert(super_trait.to_predicate(tcx))) + .find(|&super_trait| visited.insert(super_trait.upcast(tcx))) { // Push it to the stack for the next iteration of 'diving_in to pick up Some(unvisited_super_trait) => { @@ -165,7 +165,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( } if let Some(next_inner_most_trait_ref) = - siblings.find(|&sibling| visited.insert(sibling.to_predicate(tcx))) + siblings.find(|&sibling| visited.insert(sibling.upcast(tcx))) { // We're throwing away potential constness of super traits here. // FIXME: handle ~const super traits diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 6d84523da8a..f4189ff0902 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -377,7 +377,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let item = self.item; let extend = |traits::PredicateObligation { predicate, mut cause, .. }| { - if let Some(parent_trait_pred) = predicate.to_opt_poly_trait_pred() { + if let Some(parent_trait_pred) = predicate.as_trait_clause() { cause = cause.derived_cause( parent_trait_pred, traits::ObligationCauseCode::WellFormedDerived, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index fd7e2fec389..9090bb30f89 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -37,7 +37,7 @@ fn fn_sig_for_fn_abi<'tcx>( [], tcx.thread_local_ptr_ty(instance.def_id()), false, - hir::Unsafety::Normal, + hir::Safety::Safe, rustc_target::spec::abi::Abi::Unadjusted, )); } @@ -96,7 +96,7 @@ fn fn_sig_for_fn_abi<'tcx>( iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ), bound_vars, @@ -150,7 +150,7 @@ fn fn_sig_for_fn_abi<'tcx>( args.as_coroutine_closure().coroutine_captures_by_ref_ty(), ), sig.c_variadic, - sig.unsafety, + sig.safety, sig.abi, ), bound_vars, @@ -301,7 +301,7 @@ fn fn_sig_for_fn_abi<'tcx>( [env_ty, resume_ty], ret_ty, false, - hir::Unsafety::Normal, + hir::Safety::Safe, rustc_target::spec::abi::Abi::Rust, ) } else { @@ -310,7 +310,7 @@ fn fn_sig_for_fn_abi<'tcx>( [env_ty], ret_ty, false, - hir::Unsafety::Normal, + hir::Safety::Safe, rustc_target::spec::abi::Abi::Rust, ) }; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 492cc1d55cb..3094956fa5f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -6,7 +6,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt, TypeVisitor}; -use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, Upcast}; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits; @@ -220,7 +220,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { }, self.bound_vars, ) - .to_predicate(self.tcx), + .upcast(self.tcx), ); // We walk the *un-shifted* alias ty, because we're tracking the de bruijn diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index efefd174cd6..1c30f03c693 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,11 +1,12 @@ #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; use std::hash::Hash; +use std::ops::Index; use crate::inherent::*; -use crate::{Interner, UniverseIndex}; +use crate::{self as ty, Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are @@ -257,3 +258,139 @@ pub enum CanonicalTyVarKind { /// Floating-point type variable `?F` (that can only be unified with float types). Float, } + +/// A set of values corresponding to the canonical variables from some +/// `Canonical`. You can give these values to +/// `canonical_value.instantiate` to instantiate them into the canonical +/// value at the right places. +/// +/// When you canonicalize a value `V`, you get back one of these +/// vectors with the original values that were replaced by canonical +/// variables. You will need to supply it later to instantiate the +/// canonicalized query response. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Hash(bound = ""), + Debug(bound = "") +)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct CanonicalVarValues<I: Interner> { + pub var_values: I::GenericArgs, +} + +impl<I: Interner> CanonicalVarValues<I> { + pub fn is_identity(&self) -> bool { + self.var_values.into_iter().enumerate().all(|(bv, arg)| match arg.kind() { + ty::GenericArgKind::Lifetime(r) => { + matches!(r.kind(), ty::ReBound(ty::INNERMOST, br) if br.var().as_usize() == bv) + } + ty::GenericArgKind::Type(ty) => { + matches!(ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var().as_usize() == bv) + } + ty::GenericArgKind::Const(ct) => { + matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.var().as_usize() == bv) + } + }) + } + + pub fn is_identity_modulo_regions(&self) -> bool { + let mut var = ty::BoundVar::ZERO; + for arg in self.var_values { + match arg.kind() { + ty::GenericArgKind::Lifetime(r) => { + if matches!(r.kind(), ty::ReBound(ty::INNERMOST, br) if var == br.var()) { + var = var + 1; + } else { + // It's ok if this region var isn't an identity variable + } + } + ty::GenericArgKind::Type(ty) => { + if matches!(ty.kind(), ty::Bound(ty::INNERMOST, bt) if var == bt.var()) { + var = var + 1; + } else { + return false; + } + } + ty::GenericArgKind::Const(ct) => { + if matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if var == bc.var()) + { + var = var + 1; + } else { + return false; + } + } + } + } + + true + } + + // Given a list of canonical variables, construct a set of values which are + // the identity response. + pub fn make_identity(tcx: I, infos: I::CanonicalVars) -> CanonicalVarValues<I> { + CanonicalVarValues { + var_values: tcx.mk_args_from_iter(infos.into_iter().enumerate().map( + |(i, info)| -> I::GenericArg { + match info.kind { + CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { + Ty::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i)) + .into() + } + CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { + Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i)) + .into() + } + CanonicalVarKind::Effect => Const::new_anon_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(i), + Ty::new_bool(tcx), + ) + .into(), + CanonicalVarKind::Const(_, ty) + | CanonicalVarKind::PlaceholderConst(_, ty) => Const::new_anon_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(i), + ty, + ) + .into(), + } + }, + )), + } + } + + /// Creates dummy var values which should not be used in a + /// canonical response. + pub fn dummy() -> CanonicalVarValues<I> { + CanonicalVarValues { var_values: Default::default() } + } + + #[inline] + pub fn len(&self) -> usize { + self.var_values.len() + } +} + +impl<'a, I: Interner> IntoIterator for &'a CanonicalVarValues<I> { + type Item = I::GenericArg; + type IntoIter = <I::GenericArgs as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.var_values.into_iter() + } +} + +impl<I: Interner> Index<ty::BoundVar> for CanonicalVarValues<I> { + type Output = I::GenericArg; + + fn index(&self, value: ty::BoundVar) -> &I::GenericArg { + &self.var_values[value.as_usize()] + } +} diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs new file mode 100644 index 00000000000..622a4080608 --- /dev/null +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -0,0 +1,18 @@ +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; + +use crate::Interner; + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Debug(bound = ""), + Eq(bound = ""), + PartialEq(bound = "") +)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub enum GenericArgKind<I: Interner> { + Lifetime(I::Region), + Type(I::Ty), + Const(I::Const), +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 92b1e08ab0a..5289dfd932f 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -1,3 +1,8 @@ +//! Set of traits which are used to emulate the inherent impls that are present in `rustc_middle`. +//! It is customary to glob-import `rustc_type_ir::inherent::*` to bring all of these traits into +//! scope when programming in interner-agnostic settings, and to avoid importing any of these +//! directly elsewhere (i.e. specify the full path for an implementation downstream). + use std::fmt::Debug; use std::hash::Hash; use std::ops::Deref; @@ -21,11 +26,28 @@ pub trait Ty<I: Interner<Ty = Self>>: + TypeSuperFoldable<I> + Flags { + fn new_bool(interner: I) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy<I>) -> Self; } +pub trait Tys<I: Interner<Tys = Self>>: + Copy + Debug + Hash + Eq + IntoIterator<Item = I::Ty> + Deref<Target: Deref<Target = [I::Ty]>> +{ + fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty); +} + +pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq { + /// Whether this ABI is `extern "Rust"`. + fn is_rust(self) -> bool; +} + +pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq { + fn prefix_str(self) -> &'static str; +} + pub trait Region<I: Interner<Region = Self>>: Copy + DebugWithInfcx<I> + Hash + Eq + Into<I::GenericArg> + IntoKind<Kind = RegionKind<I>> + Flags { @@ -64,6 +86,7 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>: + Eq + IntoIterator<Item = I::GenericArg> + Deref<Target: Deref<Target = [I::GenericArg]>> + + Default { fn type_at(self, i: usize) -> I::Ty; @@ -96,3 +119,7 @@ pub trait BoundVars<I: Interner> { fn has_no_bound_vars(&self) -> bool; } + +pub trait BoundVarLike<I: Interner> { + fn var(self) -> BoundVar; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index d6680977168..9acf7c04dd6 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -1,14 +1,16 @@ use smallvec::SmallVec; use std::fmt::Debug; use std::hash::Hash; +use std::ops::Deref; use crate::inherent::*; use crate::ir_print::IrPrint; +use crate::solve::inspect::GoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, - DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, NormalizesTo, ProjectionPredicate, - SubtypePredicate, TraitPredicate, TraitRef, + DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, FnSig, GenericArgKind, + NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait Interner: @@ -24,14 +26,16 @@ pub trait Interner: + IrPrint<NormalizesTo<Self>> + IrPrint<SubtypePredicate<Self>> + IrPrint<CoercePredicate<Self>> + + IrPrint<FnSig<Self>> { type DefId: Copy + Debug + Hash + Eq; - type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>; type AdtDef: Copy + Debug + Hash + Eq; type GenericArgs: GenericArgs<Self>; - type GenericArgsSlice: Copy + Debug + Hash + Eq; - type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq; + /// The slice of args for a specific item. For a GAT like `type Foo<'a>`, it will be `['a]`, + /// not including the args from the parent item (trait or impl). + type OwnItemArgs: Copy + Debug + Hash + Eq; + type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq + IntoKind<Kind = GenericArgKind<Self>>; type Term: Copy + Debug + Hash + Eq; type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>; @@ -39,12 +43,17 @@ pub trait Interner: type BoundVar; type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>; + type PredefinedOpaques: Copy + Debug + Hash + Eq; + type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>; + type ExternalConstraints: Copy + Debug + Hash + Eq; + type GoalEvaluationSteps: Copy + Debug + Hash + Eq + Deref<Target = [GoalEvaluationStep<Self>]>; // Kinds of tys type Ty: Ty<Self>; - type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>; + type Tys: Tys<Self>; + type FnInputTys: Copy + Debug + Hash + Eq + Deref<Target = [Self::Ty]>; type ParamTy: Copy + Debug + Hash + Eq; - type BoundTy: Copy + Debug + Hash + Eq; + type BoundTy: Copy + Debug + Hash + Eq + BoundVarLike<Self>; type PlaceholderTy: PlaceholderLike; // Things stored inside of tys @@ -53,13 +62,15 @@ pub trait Interner: type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Eq; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>; + type Safety: Safety<Self>; + type Abi: Abi<Self>; // Kinds of consts type Const: Const<Self>; type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq; type PlaceholderConst: PlaceholderLike; type ParamConst: Copy + Debug + Hash + Eq; - type BoundConst: Copy + Debug + Hash + Eq; + type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike<Self>; type ValueConst: Copy + Debug + Hash + Eq; type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq; @@ -67,11 +78,12 @@ pub trait Interner: type Region: Region<Self>; type EarlyParamRegion: Copy + Debug + Hash + Eq; type LateParamRegion: Copy + Debug + Hash + Eq; - type BoundRegion: Copy + Debug + Hash + Eq; + type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike<Self>; type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Eq; type PlaceholderRegion: PlaceholderLike; // Predicates + type ParamEnv: Copy + Debug + Hash + Eq; type Predicate: Predicate<Self>; type TraitPredicate: Copy + Debug + Hash + Eq; type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; @@ -99,7 +111,7 @@ pub trait Interner: self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (TraitRef<Self>, Self::GenericArgsSlice); + ) -> (TraitRef<Self>, Self::OwnItemArgs); fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 2a766d0bc09..af4b9eef14b 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -1,8 +1,8 @@ use std::fmt; use crate::{ - AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, - NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, + AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig, + Interner, NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait IrPrint<T> { @@ -45,6 +45,7 @@ define_display_via_print!( CoercePredicate, AliasTy, AliasTerm, + FnSig, ); define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 4560a54da82..fa9bda9a2f7 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -19,13 +19,13 @@ use std::sync::Arc as Lrc; #[macro_use] pub mod visit; - #[cfg(feature = "nightly")] pub mod codec; pub mod fold; pub mod inherent; pub mod ir_print; pub mod lift; +pub mod solve; pub mod ty_info; pub mod ty_kind; @@ -35,11 +35,13 @@ mod canonical; mod const_kind; mod debug; mod flags; +mod generic_arg; mod infcx; mod interner; mod predicate; mod predicate_kind; mod region_kind; +mod upcast; pub use canonical::*; #[cfg(feature = "nightly")] @@ -47,6 +49,7 @@ pub use codec::*; pub use const_kind::*; pub use debug::{DebugWithInfcx, WithInfcx}; pub use flags::*; +pub use generic_arg::*; pub use infcx::InferCtxtLike; pub use interner::*; pub use predicate::*; @@ -54,6 +57,7 @@ pub use predicate_kind::*; pub use region_kind::*; pub use ty_info::*; pub use ty_kind::*; +pub use upcast::*; pub use AliasTyKind::*; pub use DynKind::*; pub use InferTy::*; @@ -366,6 +370,12 @@ rustc_index::newtype_index! { pub struct BoundVar {} } +impl<I: Interner> inherent::BoundVarLike<I> for BoundVar { + fn var(self) -> BoundVar { + self + } +} + /// Represents the various closure traits in the language. This /// will determine the type of the environment (`self`, in the /// desugaring) argument that the closure expects. diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index b6c7c2c348c..c0619d782c6 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::hash::Hash; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; @@ -497,7 +498,7 @@ impl<I: Interner> AliasTerm<I> { /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, /// then this function would return a `T: StreamingIterator` trait reference and /// `['a]` as the own args. - pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) { + pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::OwnItemArgs) { interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) } diff --git a/compiler/rustc_type_ir/src/solve.rs b/compiler/rustc_type_ir/src/solve.rs new file mode 100644 index 00000000000..3c24e851d7b --- /dev/null +++ b/compiler/rustc_type_ir/src/solve.rs @@ -0,0 +1,278 @@ +pub mod inspect; + +use std::fmt; +use std::hash::Hash; + +#[cfg(feature = "nightly")] +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; + +use crate::{Canonical, CanonicalVarValues, Interner, Upcast}; + +pub type CanonicalInput<I, T = <I as Interner>::Predicate> = Canonical<I, QueryInput<I, T>>; +pub type CanonicalResponse<I> = Canonical<I, Response<I>>; +/// The result of evaluating a canonical query. +/// +/// FIXME: We use a different type than the existing canonical queries. This is because +/// we need to add a `Certainty` for `overflow` and may want to restructure this code without +/// having to worry about changes to currently used code. Once we've made progress on this +/// solver, merge the two responses again. +pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>; + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(TypeFoldable_Generic, TypeVisitable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub struct NoSolution; + +/// A goal is a statement, i.e. `predicate`, we want to prove +/// given some assumptions, i.e. `param_env`. +/// +/// Most of the time the `param_env` contains the `where`-bounds of the function +/// we're currently typechecking while the `predicate` is some trait bound. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = "P: Clone"), + Copy(bound = "P: Copy"), + Hash(bound = "P: Hash"), + PartialEq(bound = "P: PartialEq"), + Eq(bound = "P: Eq"), + Debug(bound = "P: fmt::Debug") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct Goal<I: Interner, P> { + pub param_env: I::ParamEnv, + pub predicate: P, +} + +impl<I: Interner, P> Goal<I, P> { + pub fn new(tcx: I, param_env: I::ParamEnv, predicate: impl Upcast<I, P>) -> Goal<I, P> { + Goal { param_env, predicate: predicate.upcast(tcx) } + } + + /// Updates the goal to one with a different `predicate` but the same `param_env`. + pub fn with<Q>(self, tcx: I, predicate: impl Upcast<I, Q>) -> Goal<I, Q> { + Goal { param_env: self.param_env, predicate: predicate.upcast(tcx) } + } +} + +/// Why a specific goal has to be proven. +/// +/// This is necessary as we treat nested goals different depending on +/// their source. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub enum GoalSource { + Misc, + /// We're proving a where-bound of an impl. + /// + /// FIXME(-Znext-solver=coinductive): Explain how and why this + /// changes whether cycles are coinductive. + /// + /// This also impacts whether we erase constraints on overflow. + /// Erasing constraints is generally very useful for perf and also + /// results in better error messages by avoiding spurious errors. + /// We do not erase overflow constraints in `normalizes-to` goals unless + /// they are from an impl where-clause. This is necessary due to + /// backwards compatability, cc trait-system-refactor-initiatitive#70. + ImplWhereBound, + /// Instantiating a higher-ranked goal and re-proving it. + InstantiateHigherRanked, +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = "Goal<I, P>: Clone"), + Copy(bound = "Goal<I, P>: Copy"), + Hash(bound = "Goal<I, P>: Hash"), + PartialEq(bound = "Goal<I, P>: PartialEq"), + Eq(bound = "Goal<I, P>: Eq"), + Debug(bound = "Goal<I, P>: fmt::Debug") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct QueryInput<I: Interner, P> { + pub goal: Goal<I, P>, + pub predefined_opaques_in_body: I::PredefinedOpaques, +} + +/// Possible ways the given goal can be proven. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +pub enum CandidateSource<I: Interner> { + /// A user written impl. + /// + /// ## Examples + /// + /// ```rust + /// fn main() { + /// let x: Vec<u32> = Vec::new(); + /// // This uses the impl from the standard library to prove `Vec<T>: Clone`. + /// let y = x.clone(); + /// } + /// ``` + Impl(I::DefId), + /// A builtin impl generated by the compiler. When adding a new special + /// trait, try to use actual impls whenever possible. Builtin impls should + /// only be used in cases where the impl cannot be manually be written. + /// + /// Notable examples are auto traits, `Sized`, and `DiscriminantKind`. + /// For a list of all traits with builtin impls, check out the + /// `EvalCtxt::assemble_builtin_impl_candidates` method. + BuiltinImpl(BuiltinImplSource), + /// An assumption from the environment. + /// + /// More precisely we've used the `n-th` assumption in the `param_env`. + /// + /// ## Examples + /// + /// ```rust + /// fn is_clone<T: Clone>(x: T) -> (T, T) { + /// // This uses the assumption `T: Clone` from the `where`-bounds + /// // to prove `T: Clone`. + /// (x.clone(), x) + /// } + /// ``` + ParamEnv(usize), + /// If the self type is an alias type, e.g. an opaque type or a projection, + /// we know the bounds on that alias to hold even without knowing its concrete + /// underlying type. + /// + /// More precisely this candidate is using the `n-th` bound in the `item_bounds` of + /// the self type. + /// + /// ## Examples + /// + /// ```rust + /// trait Trait { + /// type Assoc: Clone; + /// } + /// + /// fn foo<T: Trait>(x: <T as Trait>::Assoc) { + /// // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in + /// // in the trait definition. + /// let _y = x.clone(); + /// } + /// ``` + AliasBound, + /// A candidate that is registered only during coherence to represent some + /// yet-unknown impl that could be produced downstream without violating orphan + /// rules. + // FIXME: Merge this with the forced ambiguity candidates, so those don't use `Misc`. + CoherenceUnknowable, +} + +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))] +pub enum BuiltinImplSource { + /// Some builtin impl we don't need to differentiate. This should be used + /// unless more specific information is necessary. + Misc, + /// A builtin impl for trait objects. + /// + /// The vtable is formed by concatenating together the method lists of + /// the base object trait and all supertraits, pointers to supertrait vtable will + /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods + /// in that vtable. + Object { vtable_base: usize }, + /// The vtable is formed by concatenating together the method lists of + /// the base object trait and all supertraits, pointers to supertrait vtable will + /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable + /// within that vtable. + TraitUpcasting { vtable_vptr_slot: Option<usize> }, + /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`. + /// + /// This needs to be a separate variant as it is still unstable and we need to emit + /// a feature error when using it on stable. + TupleUnsizing, +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub struct Response<I: Interner> { + pub certainty: Certainty, + pub var_values: CanonicalVarValues<I>, + /// Additional constraints returned by this query. + pub external_constraints: I::ExternalConstraints, +} + +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub enum Certainty { + Yes, + Maybe(MaybeCause), +} + +impl Certainty { + pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity); + + /// Use this function to merge the certainty of multiple nested subgoals. + /// + /// Given an impl like `impl<T: Foo + Bar> Baz for T {}`, we have 2 nested + /// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`. + /// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in + /// success, we merge these two responses. This results in ambiguity. + /// + /// If we unify ambiguity with overflow, we return overflow. This doesn't matter + /// inside of the solver as we do not distinguish ambiguity from overflow. It does + /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` + /// in ambiguity without changing the inference state, we still want to tell the + /// user that `T: Baz` results in overflow. + pub fn unify_with(self, other: Certainty) -> Certainty { + match (self, other) { + (Certainty::Yes, Certainty::Yes) => Certainty::Yes, + (Certainty::Yes, Certainty::Maybe(_)) => other, + (Certainty::Maybe(_), Certainty::Yes) => self, + (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.unify_with(b)), + } + } + + pub const fn overflow(suggest_increasing_limit: bool) -> Certainty { + Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }) + } +} + +/// Why we failed to evaluate a goal. +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub enum MaybeCause { + /// We failed due to ambiguity. This ambiguity can either + /// be a true ambiguity, i.e. there are multiple different answers, + /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals. + Ambiguity, + /// We gave up due to an overflow, most often by hitting the recursion limit. + Overflow { suggest_increasing_limit: bool }, +} + +impl MaybeCause { + fn unify_with(self, other: MaybeCause) -> MaybeCause { + match (self, other) { + (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, + (MaybeCause::Ambiguity, MaybeCause::Overflow { .. }) => other, + (MaybeCause::Overflow { .. }, MaybeCause::Ambiguity) => self, + ( + MaybeCause::Overflow { suggest_increasing_limit: a }, + MaybeCause::Overflow { suggest_increasing_limit: b }, + ) => MaybeCause::Overflow { suggest_increasing_limit: a || b }, + } + } +} diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index 9e944899026..c4f6ee2669b 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -18,16 +18,19 @@ //! //! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -use super::{ - CandidateSource, Canonical, CanonicalInput, Certainty, Goal, GoalSource, NoSolution, - QueryInput, QueryResult, -}; -use crate::{infer::canonical::CanonicalVarValues, ty}; -use format::ProofTreeFormatter; -use rustc_macros::{TypeFoldable, TypeVisitable}; +mod format; + use std::fmt::{Debug, Write}; +use std::hash::Hash; -mod format; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; + +use self::format::ProofTreeFormatter; +use crate::solve::{ + CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, NoSolution, QueryInput, + QueryResult, +}; +use crate::{Canonical, CanonicalVarValues, Interner}; /// Some `data` together with information about how they relate to the input /// of the canonical query. @@ -35,96 +38,113 @@ mod format; /// This is only ever used as [CanonicalState]. Any type information in proof /// trees used mechanically has to be canonicalized as we otherwise leak /// inference variables from a nested `InferCtxt`. -#[derive(Debug, Clone, Copy, Eq, PartialEq, TypeFoldable, TypeVisitable)] -pub struct State<'tcx, T> { - pub var_values: CanonicalVarValues<'tcx>, +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = "T: Clone"), + Copy(bound = "T: Copy"), + PartialEq(bound = "T: PartialEq"), + Eq(bound = "T: Eq"), + Hash(bound = "T: Hash"), + Debug(bound = "T: Debug") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub struct State<I: Interner, T> { + pub var_values: CanonicalVarValues<I>, pub data: T, } -pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>; +pub type CanonicalState<I, T> = Canonical<I, State<I, T>>; /// When evaluating the root goals we also store the /// original values for the `CanonicalVarValues` of the /// canonicalized goal. We use this to map any [CanonicalState] /// from the local `InferCtxt` of the solver query to /// the `InferCtxt` of the caller. -#[derive(Eq, PartialEq)] -pub enum GoalEvaluationKind<'tcx> { - Root { orig_values: Vec<ty::GenericArg<'tcx>> }, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub enum GoalEvaluationKind<I: Interner> { + Root { orig_values: Vec<I::GenericArg> }, Nested, } -#[derive(Eq, PartialEq)] -pub struct GoalEvaluation<'tcx> { - pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, - pub kind: GoalEvaluationKind<'tcx>, - pub evaluation: CanonicalGoalEvaluation<'tcx>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +pub struct GoalEvaluation<I: Interner> { + pub uncanonicalized_goal: Goal<I, I::Predicate>, + pub kind: GoalEvaluationKind<I>, + pub evaluation: CanonicalGoalEvaluation<I>, } -#[derive(Eq, PartialEq, Debug)] -pub struct CanonicalGoalEvaluation<'tcx> { - pub goal: CanonicalInput<'tcx>, - pub kind: CanonicalGoalEvaluationKind<'tcx>, - pub result: QueryResult<'tcx>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub struct CanonicalGoalEvaluation<I: Interner> { + pub goal: CanonicalInput<I>, + pub kind: CanonicalGoalEvaluationKind<I>, + pub result: QueryResult<I>, } -#[derive(Eq, PartialEq, Debug)] -pub enum CanonicalGoalEvaluationKind<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub enum CanonicalGoalEvaluationKind<I: Interner> { Overflow, CycleInStack, ProvisionalCacheHit, - Evaluation { revisions: &'tcx [GoalEvaluationStep<'tcx>] }, + Evaluation { revisions: I::GoalEvaluationSteps }, } -impl Debug for GoalEvaluation<'_> { +impl<I: Interner> Debug for GoalEvaluation<I> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ProofTreeFormatter::new(f).format_goal_evaluation(self) } } -#[derive(Eq, PartialEq)] -pub struct AddedGoalsEvaluation<'tcx> { - pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub struct AddedGoalsEvaluation<I: Interner> { + pub evaluations: Vec<Vec<GoalEvaluation<I>>>, pub result: Result<Certainty, NoSolution>, } -#[derive(Eq, PartialEq, Debug)] -pub struct GoalEvaluationStep<'tcx> { - pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub struct GoalEvaluationStep<I: Interner> { + pub instantiated_goal: QueryInput<I, I::Predicate>, /// The actual evaluation of the goal, always `ProbeKind::Root`. - pub evaluation: Probe<'tcx>, + pub evaluation: Probe<I>, } /// A self-contained computation during trait solving. This either /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation /// of a goal. -#[derive(Eq, PartialEq)] -pub struct Probe<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +pub struct Probe<I: Interner> { /// What happened inside of this probe in chronological order. - pub steps: Vec<ProbeStep<'tcx>>, - pub kind: ProbeKind<'tcx>, - pub final_state: CanonicalState<'tcx, ()>, + pub steps: Vec<ProbeStep<I>>, + pub kind: ProbeKind<I>, + pub final_state: CanonicalState<I, ()>, } -impl Debug for Probe<'_> { +impl<I: Interner> Debug for Probe<I> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ProofTreeFormatter::new(f).format_probe(self) } } -#[derive(Eq, PartialEq)] -pub enum ProbeStep<'tcx> { +#[derive(derivative::Derivative)] +#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +pub enum ProbeStep<I: Interner> { /// We added a goal to the `EvalCtxt` which will get proven /// the next time `EvalCtxt::try_evaluate_added_goals` is called. - AddGoal(GoalSource, CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>), + AddGoal(GoalSource, CanonicalState<I, Goal<I, I::Predicate>>), /// The inside of a `EvalCtxt::try_evaluate_added_goals` call. - EvaluateGoals(AddedGoalsEvaluation<'tcx>), + EvaluateGoals(AddedGoalsEvaluation<I>), /// A call to `probe` while proving the current goal. This is /// used whenever there are multiple candidates to prove the /// current goalby . - NestedProbe(Probe<'tcx>), + NestedProbe(Probe<I>), /// A trait goal was satisfied by an impl candidate. - RecordImplArgs { impl_args: CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> }, + RecordImplArgs { impl_args: CanonicalState<I, I::GenericArgs> }, /// A call to `EvalCtxt::evaluate_added_goals_make_canonical_response` with /// `Certainty` was made. This is the certainty passed in, so it's not unified /// with the certainty of the `try_evaluate_added_goals` that is done within; @@ -136,16 +156,25 @@ pub enum ProbeStep<'tcx> { /// What kind of probe we're in. In case the probe represents a candidate, or /// the final result of the current goal - via [ProbeKind::Root] - we also /// store the [QueryResult]. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum ProbeKind<'tcx> { +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Hash(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub enum ProbeKind<I: Interner> { /// The root inference context while proving a goal. - Root { result: QueryResult<'tcx> }, + Root { result: QueryResult<I> }, /// Trying to normalize an alias by at least one step in `NormalizesTo`. - TryNormalizeNonRigid { result: QueryResult<'tcx> }, + TryNormalizeNonRigid { result: QueryResult<I> }, /// Probe entered when normalizing the self ty during candidate assembly NormalizedSelfTyAssembly, /// A candidate for proving a trait or alias-relate goal. - TraitCandidate { source: CandidateSource, result: QueryResult<'tcx> }, + TraitCandidate { source: CandidateSource<I>, result: QueryResult<I> }, /// Used in the probe that wraps normalizing the non-self type for the unsize /// trait, which is also structurally matched on. UnsizeAssembly, @@ -156,5 +185,5 @@ pub enum ProbeKind<'tcx> { /// Looking for param-env candidates that satisfy the trait ref for a projection. ShadowedEnvProbing, /// Try to unify an opaque type with an existing key in the storage. - OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, + OpaqueTypeStorageLookup { result: QueryResult<I> }, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_type_ir/src/solve/inspect/format.rs index 5b3c50cb973..44ade04cf98 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_type_ir/src/solve/inspect/format.rs @@ -1,7 +1,10 @@ +use std::marker::PhantomData; + use super::*; -pub(super) struct ProofTreeFormatter<'a, 'b> { +pub(super) struct ProofTreeFormatter<'a, 'b, I> { f: &'a mut (dyn Write + 'b), + _interner: PhantomData<I>, } enum IndentorState { @@ -36,23 +39,24 @@ impl Write for Indentor<'_, '_> { } } -impl<'a, 'b> ProofTreeFormatter<'a, 'b> { +impl<'a, 'b, I: Interner> ProofTreeFormatter<'a, 'b, I> { pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self { - ProofTreeFormatter { f } + ProofTreeFormatter { f, _interner: PhantomData } } fn nested<F>(&mut self, func: F) -> std::fmt::Result where - F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> std::fmt::Result, + F: FnOnce(&mut ProofTreeFormatter<'_, '_, I>) -> std::fmt::Result, { write!(self.f, " {{")?; func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline }, + _interner: PhantomData, })?; writeln!(self.f, "}}") } - pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result { + pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<I>) -> std::fmt::Result { let goal_text = match eval.kind { GoalEvaluationKind::Root { orig_values: _ } => "ROOT GOAL", GoalEvaluationKind::Nested => "GOAL", @@ -63,7 +67,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_canonical_goal_evaluation( &mut self, - eval: &CanonicalGoalEvaluation<'_>, + eval: &CanonicalGoalEvaluation<I>, ) -> std::fmt::Result { writeln!(self.f, "GOAL: {:?}", eval.goal)?; @@ -89,13 +93,13 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_evaluation_step( &mut self, - evaluation_step: &GoalEvaluationStep<'_>, + evaluation_step: &GoalEvaluationStep<I>, ) -> std::fmt::Result { writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; self.format_probe(&evaluation_step.evaluation) } - pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result { + pub(super) fn format_probe(&mut self, probe: &Probe<I>) -> std::fmt::Result { match &probe.kind { ProbeKind::Root { result } => { write!(self.f, "ROOT RESULT: {result:?}") @@ -150,7 +154,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_added_goals_evaluation( &mut self, - added_goals_evaluation: &AddedGoalsEvaluation<'_>, + added_goals_evaluation: &AddedGoalsEvaluation<I>, ) -> std::fmt::Result { writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 672c890f94e..629ea9fb839 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -342,7 +342,7 @@ impl<I: Interner> PartialEq for TyKind<I> { impl<I: Interner> DebugWithInfcx<I> for TyKind<I> { fn fmt<Infcx: InferCtxtLike<Interner = I>>( this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, + f: &mut fmt::Formatter<'_>, ) -> fmt::Result { match this.data { Bool => write!(f, "bool"), @@ -514,7 +514,7 @@ impl<I: Interner> AliasTy<I> { /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, /// then this function would return a `T: StreamingIterator` trait reference and /// `['a]` as the own args. - pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) { + pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::OwnItemArgs) { debug_assert_eq!(self.kind(interner), AliasTyKind::Projection); interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) } @@ -561,8 +561,8 @@ impl<I: Interner> fmt::Debug for AliasTy<I> { impl<I: Interner> DebugWithInfcx<I> for AliasTy<I> { fn fmt<Infcx: InferCtxtLike<Interner = I>>( this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { f.debug_struct("AliasTy") .field("args", &this.map(|data| data.args)) .field("def_id", &this.data.def_id) @@ -952,3 +952,76 @@ pub struct TypeAndMut<I: Interner> { pub ty: I::Ty, pub mutbl: Mutability, } + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Hash(bound = "") +)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct FnSig<I: Interner> { + pub inputs_and_output: I::Tys, + pub c_variadic: bool, + pub safety: I::Safety, + pub abi: I::Abi, +} + +impl<I: Interner> FnSig<I> { + pub fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty) { + self.inputs_and_output.split_inputs_and_output() + } + + pub fn inputs(self) -> I::FnInputTys { + self.split_inputs_and_output().0 + } + + pub fn output(self) -> I::Ty { + self.split_inputs_and_output().1 + } +} + +impl<I: Interner> fmt::Debug for FnSig<I> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl<I: Interner> DebugWithInfcx<I> for FnSig<I> { + fn fmt<Infcx: InferCtxtLike<Interner = I>>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + let sig = this.data; + let FnSig { inputs_and_output: _, c_variadic, safety, abi } = sig; + + write!(f, "{}", safety.prefix_str())?; + if !abi.is_rust() { + write!(f, "extern \"{abi:?}\" ")?; + } + + write!(f, "fn(")?; + let (inputs, output) = sig.split_inputs_and_output(); + for (i, ty) in inputs.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", &this.wrap(ty))?; + } + if *c_variadic { + if inputs.is_empty() { + write!(f, "...")?; + } else { + write!(f, ", ...")?; + } + } + write!(f, ")")?; + + match output.kind() { + Tuple(list) if list.is_empty() => Ok(()), + _ => write!(f, " -> {:?}", &this.wrap(sig.output())), + } + } +} diff --git a/compiler/rustc_type_ir/src/upcast.rs b/compiler/rustc_type_ir/src/upcast.rs new file mode 100644 index 00000000000..2049337c351 --- /dev/null +++ b/compiler/rustc_type_ir/src/upcast.rs @@ -0,0 +1,24 @@ +/// An `Into`-like trait that takes `TyCtxt` to perform interner-specific transformations. +pub trait Upcast<I, T> { + fn upcast(self, interner: I) -> T; +} + +impl<I, T, U> Upcast<I, U> for T +where + U: UpcastFrom<I, T>, +{ + fn upcast(self, interner: I) -> U { + U::upcast_from(self, interner) + } +} + +/// A `From`-like trait that takes `TyCtxt` to perform interner-specific transformations. +pub trait UpcastFrom<I, T> { + fn upcast_from(from: T, interner: I) -> Self; +} + +impl<I, T> UpcastFrom<I, T> for T { + fn upcast_from(from: T, _tcx: I) -> Self { + from + } +} diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index e077c580318..a1432acf93c 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -915,8 +915,8 @@ pub enum Mutability { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Safety { + Safe, Unsafe, - Normal, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 56251613840..759e3f166bd 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1,6 +1,5 @@ use super::{ - mir::Safety, - mir::{Body, Mutability}, + mir::{Body, Mutability, Safety}, with, DefId, Error, Symbol, }; use crate::abi::Layout; @@ -909,7 +908,7 @@ pub type PolyFnSig = Binder<FnSig>; pub struct FnSig { pub inputs_and_output: Vec<Ty>, pub c_variadic: bool, - pub unsafety: Safety, + pub safety: Safety, pub abi: Abi, } @@ -1200,7 +1199,7 @@ pub enum TraitSpecializationKind { #[derive(Clone, Debug, Eq, PartialEq)] pub struct TraitDecl { pub def_id: TraitDef, - pub unsafety: Safety, + pub safety: Safety, pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, diff --git a/config.example.toml b/config.example.toml index 224d079b206..228521747ed 100644 --- a/config.example.toml +++ b/config.example.toml @@ -653,9 +653,12 @@ # when no explicit backend is specified. #codegen-backends = ["llvm"] -# Indicates whether LLD will be compiled and made available in the sysroot for -# rustc to execute. -#lld = false +# Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and +# whether to set it as rustc's default linker on `x86_64-unknown-linux-gnu`. This will also only be +# when *not* building an external LLVM (so only when using `download-ci-llvm` or building LLVM from +# the in-tree source): setting `llvm-config` in the `[target.x86_64-unknown-linux-gnu]` section will +# make this default to false. +#lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true # Indicates whether LLD will be used to link Rust crates during bootstrap on # supported platforms. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e5d62447eb2..f1a6df94e11 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2081,6 +2081,54 @@ impl<I> FromIterator<I> for Box<[I]> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl FromIterator<char> for Box<str> { + fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a> FromIterator<&'a char> for Box<str> { + fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a> FromIterator<&'a str> for Box<str> { + fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl FromIterator<String> for Box<str> { + fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl<A: Allocator> FromIterator<Box<str, A>> for Box<str> { + fn from_iter<T: IntoIterator<Item = Box<str, A>>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a> FromIterator<Cow<'a, str>> for Box<str> { + fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> { fn clone(&self) -> Self { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 2a859ad55ee..36078da7c35 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -60,6 +60,8 @@ use core::slice; use core::str::pattern::Pattern; #[cfg(not(no_global_oom_handling))] +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::collections::TryReserveError; @@ -1940,8 +1942,10 @@ impl String { /// Converts this `String` into a <code>[Box]<[str]></code>. /// - /// This will drop any excess capacity. + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. + /// Note that this call may reallocate and copy the bytes of the string. /// + /// [`shrink_to_fit`]: String::shrink_to_fit /// [str]: prim@str "str" /// /// # Examples @@ -1967,10 +1971,10 @@ impl String { /// this function is ideally used for data that lives for the remainder of the program's life, /// as dropping the returned reference will cause a memory leak. /// - /// It does not reallocate or shrink the `String`, - /// so the leaked allocation may include unused capacity that is not part - /// of the returned slice. If you don't want that, call [`into_boxed_str`], - /// and then [`Box::leak`]. + /// It does not reallocate or shrink the `String`, so the leaked allocation may include unused + /// capacity that is not part of the returned slice. If you want to discard excess capacity, + /// call [`into_boxed_str`], and then [`Box::leak`] instead. However, keep in mind that + /// trimming the capacity may result in a reallocation and copy. /// /// [`into_boxed_str`]: Self::into_boxed_str /// @@ -2155,8 +2159,8 @@ impl FromIterator<String> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str2", since = "1.45.0")] -impl FromIterator<Box<str>> for String { - fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> String { +impl<A: Allocator> FromIterator<Box<str, A>> for String { + fn from_iter<I: IntoIterator<Item = Box<str, A>>>(iter: I) -> String { let mut buf = String::new(); buf.extend(iter); buf @@ -2237,8 +2241,8 @@ impl<'a> Extend<&'a str> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str2", since = "1.45.0")] -impl Extend<Box<str>> for String { - fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) { +impl<A: Allocator> Extend<Box<str, A>> for String { + fn extend<I: IntoIterator<Item = Box<str, A>>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 935ead2699a..86c4ea9fab0 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -165,8 +165,9 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // float -> float -// FIXME(f16_f128): adding additional `From` impls for existing types breaks inference. See -// <https://github.com/rust-lang/rust/issues/123824> +// FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See +// <https://github.com/rust-lang/rust/issues/123831> +impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d1450bf12ce..d58e1dbb3e4 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1594,6 +1594,12 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn sqrtf64(x: f64) -> f64; + /// Raises an `f16` to an integer power. + /// + /// The stabilized version of this intrinsic is + /// [`f16::powi`](../../std/primitive.f16.html#method.powi) + #[rustc_nounwind] + pub fn powif16(a: f16, x: i32) -> f16; /// Raises an `f32` to an integer power. /// /// The stabilized version of this intrinsic is @@ -1606,6 +1612,12 @@ extern "rust-intrinsic" { /// [`f64::powi`](../../std/primitive.f64.html#method.powi) #[rustc_nounwind] pub fn powif64(a: f64, x: i32) -> f64; + /// Raises an `f128` to an integer power. + /// + /// The stabilized version of this intrinsic is + /// [`f128::powi`](../../std/primitive.f128.html#method.powi) + #[rustc_nounwind] + pub fn powif128(a: f128, x: i32) -> f128; /// Returns the sine of an `f32`. /// diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 8fe81a9f528..9362dc87654 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -228,6 +228,16 @@ impl f128 { /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. /// See [explanation of NaN as a special value](f32) for more info. + /// + /// ``` + /// #![feature(f128)] + /// + /// let f = 7.0_f128; + /// let g = -7.0_f128; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] @@ -241,6 +251,16 @@ impl f128 { /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. /// See [explanation of NaN as a special value](f32) for more info. + /// + /// ``` + /// #![feature(f128)] + /// + /// let f = 7.0_f128; + /// let g = -7.0_f128; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 4290245ab29..c4d4584544b 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -224,6 +224,16 @@ impl f16 { /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. /// See [explanation of NaN as a special value](f32) for more info. + /// + /// ``` + /// #![feature(f16)] + /// + /// let f = 7.0_f16; + /// let g = -7.0_f16; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] @@ -237,6 +247,16 @@ impl f16 { /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. /// See [explanation of NaN as a special value](f32) for more info. + /// + /// ``` + /// #![feature(f16)] + /// + /// let f = 7.0_f16; + /// let g = -7.0_f16; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index d56f346d95e..db8e1f318ad 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1111,7 +1111,6 @@ impl f64 { /// ``` /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); - /// /// ``` #[must_use = "this returns the result of the operation, \ without modifying the original"] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index b67930503e0..7856a1d8581 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -187,7 +187,7 @@ impl<T: ?Sized> *mut T { /// /// This is similar to `self as usize`, which semantically discards *provenance* and /// *address-space* information. However, unlike `self as usize`, casting the returned address - /// back to a pointer yields yields a [pointer without provenance][without_provenance_mut], which is undefined + /// back to a pointer yields a [pointer without provenance][without_provenance_mut], which is undefined /// behavior to dereference. To properly restore the lost information and obtain a /// dereferenceable pointer, use [`with_addr`][pointer::with_addr] or /// [`map_addr`][pointer::map_addr]. diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b2b627fe6a9..4c6dc4bba43 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -45,25 +45,29 @@ //! that make working with it more succinct. //! //! ``` +//! // The `is_ok` and `is_err` methods do what they say. //! let good_result: Result<i32, i32> = Ok(10); //! let bad_result: Result<i32, i32> = Err(10); -//! -//! // The `is_ok` and `is_err` methods do what they say. //! assert!(good_result.is_ok() && !good_result.is_err()); //! assert!(bad_result.is_err() && !bad_result.is_ok()); //! -//! // `map` consumes the `Result` and produces another. +//! // `map` and `map_err` consume the `Result` and produce another. //! let good_result: Result<i32, i32> = good_result.map(|i| i + 1); -//! let bad_result: Result<i32, i32> = bad_result.map(|i| i - 1); +//! let bad_result: Result<i32, i32> = bad_result.map_err(|i| i - 1); +//! assert_eq!(good_result, Ok(11)); +//! assert_eq!(bad_result, Err(9)); //! //! // Use `and_then` to continue the computation. //! let good_result: Result<bool, i32> = good_result.and_then(|i| Ok(i == 11)); +//! assert_eq!(good_result, Ok(true)); //! //! // Use `or_else` to handle the error. //! let bad_result: Result<i32, i32> = bad_result.or_else(|i| Ok(i + 20)); +//! assert_eq!(bad_result, Ok(29)); //! //! // Consume the result and return the contents with `unwrap`. //! let final_awesome_result = good_result.unwrap(); +//! assert!(final_awesome_result) //! ``` //! //! # Results must be used diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9bee50424b3..f82f965e67c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4533,21 +4533,21 @@ impl<T, const N: usize> [[T; N]] { /// ``` /// #![feature(slice_flatten)] /// - /// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten(), &[1, 2, 3, 4, 5, 6]); + /// assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]); /// /// assert_eq!( - /// [[1, 2, 3], [4, 5, 6]].flatten(), - /// [[1, 2], [3, 4], [5, 6]].flatten(), + /// [[1, 2, 3], [4, 5, 6]].as_flattened(), + /// [[1, 2], [3, 4], [5, 6]].as_flattened(), /// ); /// /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []]; - /// assert!(slice_of_empty_arrays.flatten().is_empty()); + /// assert!(slice_of_empty_arrays.as_flattened().is_empty()); /// /// let empty_slice_of_arrays: &[[u32; 10]] = &[]; - /// assert!(empty_slice_of_arrays.flatten().is_empty()); + /// assert!(empty_slice_of_arrays.as_flattened().is_empty()); /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] - pub const fn flatten(&self) -> &[T] { + pub const fn as_flattened(&self) -> &[T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { @@ -4581,11 +4581,11 @@ impl<T, const N: usize> [[T; N]] { /// } /// /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; - /// add_5_to_all(array.flatten_mut()); + /// add_5_to_all(array.as_flattened_mut()); /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] - pub fn flatten_mut(&mut self) -> &mut [T] { + pub fn as_flattened_mut(&mut self) -> &mut [T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 72f6a3b773b..88fe29c9997 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -43,11 +43,15 @@ const DAYS_PER_WEEK: u64 = 7; #[rustc_layout_scalar_valid_range_end(999_999_999)] struct Nanoseconds(u32); +impl Nanoseconds { + // SAFETY: 0 is within the valid range + const ZERO: Self = unsafe { Nanoseconds(0) }; +} + impl Default for Nanoseconds { #[inline] fn default() -> Self { - // SAFETY: 0 is within the valid range - unsafe { Nanoseconds(0) } + Self::ZERO } } @@ -236,7 +240,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_secs(secs: u64) -> Duration { - Duration::new(secs, 0) + Duration { secs, nanos: Nanoseconds::ZERO } } /// Creates a new `Duration` from the specified number of milliseconds. @@ -256,7 +260,13 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_millis(millis: u64) -> Duration { - Duration::new(millis / MILLIS_PER_SEC, ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI) + let secs = millis / MILLIS_PER_SEC; + let subsec_millis = (millis % MILLIS_PER_SEC) as u32; + // SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000 + // => x % 1_000 < 1_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_millis * NANOS_PER_MILLI) }; + + Duration { secs, nanos: subsec_nanos } } /// Creates a new `Duration` from the specified number of microseconds. @@ -276,7 +286,13 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_micros(micros: u64) -> Duration { - Duration::new(micros / MICROS_PER_SEC, ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO) + let secs = micros / MICROS_PER_SEC; + let subsec_micros = (micros % MICROS_PER_SEC) as u32; + // SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000 + // => x % 1_000_000 < 1_000_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_micros * NANOS_PER_MICRO) }; + + Duration { secs, nanos: subsec_nanos } } /// Creates a new `Duration` from the specified number of nanoseconds. @@ -301,7 +317,13 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_nanos(nanos: u64) -> Duration { - Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32) + const NANOS_PER_SEC: u64 = self::NANOS_PER_SEC as u64; + let secs = nanos / NANOS_PER_SEC; + let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; + // SAFETY: x % 1_000_000_000 < 1_000_000_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_nanos) }; + + Duration { secs, nanos: subsec_nanos } } /// Creates a new `Duration` from the specified number of weeks. diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index ffe8ffcc7f2..c91ac2fbb43 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2609,14 +2609,14 @@ fn test_slice_from_ptr_range() { #[should_panic = "slice len overflow"] fn test_flatten_size_overflow() { let x = &[[(); usize::MAX]; 2][..]; - let _ = x.flatten(); + let _ = x.as_flattened(); } #[test] #[should_panic = "slice len overflow"] fn test_flatten_mut_size_overflow() { let x = &mut [[(); usize::MAX]; 2][..]; - let _ = x.flatten_mut(); + let _ = x.as_flattened_mut(); } #[test] diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 4710d7c50b4..491235a872e 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -7,5 +7,29 @@ #[cfg(test)] mod tests; +#[cfg(not(test))] +use crate::intrinsics; + #[unstable(feature = "f128", issue = "116909")] pub use core::f128::consts; + +#[cfg(not(test))] +impl f128 { + /// Raises a number to an integer power. + /// + /// Using this function is generally faster than using `powf`. + /// It might have a different sequence of rounding operations than `powf`, + /// so the results are not guaranteed to agree. + /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. + #[inline] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn powi(self, n: i32) -> f128 { + unsafe { intrinsics::powif128(self, n) } + } +} diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index c36f9f5d4c6..1cb655ffabd 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -7,5 +7,29 @@ #[cfg(test)] mod tests; +#[cfg(not(test))] +use crate::intrinsics; + #[unstable(feature = "f16", issue = "116909")] pub use core::f16::consts; + +#[cfg(not(test))] +impl f16 { + /// Raises a number to an integer power. + /// + /// Using this function is generally faster than using `powf`. + /// It might have a different sequence of rounding operations than `powf`, + /// so the results are not guaranteed to agree. + /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. + #[inline] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn powi(self, n: i32) -> f16 { + unsafe { intrinsics::powif16(self, n) } + } +} diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 9014bb3782a..2f908e3d0e9 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -59,8 +59,8 @@ unsafe impl GlobalAlloc for System { } cfg_if::cfg_if! { + // We use posix_memalign wherever possible, but not all targets have that function. if #[cfg(any( - target_os = "android", target_os = "redox", target_os = "espidf", target_os = "horizon", @@ -68,23 +68,6 @@ cfg_if::cfg_if! { ))] { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - // On android we currently target API level 9 which unfortunately - // doesn't have the `posix_memalign` API used below. Instead we use - // `memalign`, but this unfortunately has the property on some systems - // where the memory returned cannot be deallocated by `free`! - // - // Upon closer inspection, however, this appears to work just fine with - // Android, so for this platform we should be fine to call `memalign` - // (which is present in API level 9). Some helpful references could - // possibly be chromium using memalign [1], attempts at documenting that - // memalign + free is ok [2] [3], or the current source of chromium - // which still uses memalign on android [4]. - // - // [1]: https://codereview.chromium.org/10796020/ - // [2]: https://code.google.com/p/android/issues/detail?id=35391 - // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 - // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ - // /memory/aligned_memory.cc libc::memalign(layout.align(), layout.size()) as *mut u8 } } else { diff --git a/library/stdarch b/library/stdarch -Subproject c0257c1660e78c80ad1b9136fcc5555b14da5b4 +Subproject df3618d9f35165f4bc548114e511c49c29e1fd9 diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 48a6602e2df..66692a2a2cb 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1136,6 +1136,11 @@ pub fn rustc_cargo_env( cargo.env("CFG_DEFAULT_LINKER", s); } + // Enable rustc's env var for `rust-lld` when requested. + if builder.config.lld_enabled { + cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1"); + } + if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bb51433a3dc..19119a073c5 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1307,6 +1307,9 @@ impl Config { toml_path = config.src.join(toml_path); } + let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); + let ci_channel = file_content.trim_end(); + // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `config.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { @@ -1532,7 +1535,9 @@ impl Config { let mut debuginfo_level_tests = None; let mut optimize = None; let mut omit_git_hash = None; + let mut lld_enabled = None; + let mut is_user_configured_rust_channel = false; if let Some(rust) = toml.rust { let Rust { optimize: optimize_toml, @@ -1565,7 +1570,7 @@ impl Config { dist_src, save_toolstates, codegen_backends, - lld, + lld: lld_enabled_toml, llvm_tools, llvm_bitcode_linker, deny_warnings, @@ -1590,6 +1595,7 @@ impl Config { lld_mode, } = rust; + is_user_configured_rust_channel = channel.is_some(); set(&mut config.channel, channel); config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc); @@ -1597,8 +1603,6 @@ impl Config { if config.download_rustc_commit.is_some() { // We need the channel used by the downloaded compiler to match the one we set for rustdoc; // otherwise rustdoc-ui tests break. - let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel"))); - let ci_channel = ci_channel.trim_end(); if config.channel != ci_channel && !(config.channel == "dev" && ci_channel == "nightly") { @@ -1620,6 +1624,7 @@ impl Config { debuginfo_level_std = debuginfo_level_std_toml; debuginfo_level_tools = debuginfo_level_tools_toml; debuginfo_level_tests = debuginfo_level_tests_toml; + lld_enabled = lld_enabled_toml; config.rust_split_debuginfo_for_build_triple = split_debuginfo .as_deref() @@ -1653,18 +1658,8 @@ impl Config { config.incremental = true; } set(&mut config.lld_mode, lld_mode); - set(&mut config.lld_enabled, lld); set(&mut config.llvm_bitcode_linker_enabled, llvm_bitcode_linker); - if matches!(config.lld_mode, LldMode::SelfContained) - && !config.lld_enabled - && flags.stage.unwrap_or(0) > 0 - { - panic!( - "Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true." - ); - } - config.llvm_tools_enabled = llvm_tools.unwrap_or(true); config.rustc_parallel = parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly"); @@ -1725,6 +1720,10 @@ impl Config { config.omit_git_hash = omit_git_hash.unwrap_or(default); config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); + if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { + ci_channel.clone_into(&mut config.channel); + } + if let Some(llvm) = toml.llvm { let Llvm { optimize: optimize_toml, @@ -1954,6 +1953,43 @@ impl Config { config.llvm_plugins = llvm_plugins.unwrap_or(false); config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true)); + // We make `x86_64-unknown-linux-gnu` use the self-contained linker by default, so we will + // build our internal lld and use it as the default linker, by setting the `rust.lld` config + // to true by default: + // - on the `x86_64-unknown-linux-gnu` target + // - on the `dev` and `nightly` channels + // - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that + // we're also able to build the corresponding lld + // - or when using an external llvm that's downloaded from CI, which also contains our prebuilt + // lld + // - otherwise, we'd be using an external llvm, and lld would not necessarily available and + // thus, disabled + // - similarly, lld will not be built nor used by default when explicitly asked not to, e.g. + // when the config sets `rust.lld = false` + if config.build.triple == "x86_64-unknown-linux-gnu" + && config.hosts == [config.build] + && (config.channel == "dev" || config.channel == "nightly") + { + let no_llvm_config = config + .target_config + .get(&config.build) + .is_some_and(|target_config| target_config.llvm_config.is_none()); + let enable_lld = config.llvm_from_ci || no_llvm_config; + // Prefer the config setting in case an explicit opt-out is needed. + config.lld_enabled = lld_enabled.unwrap_or(enable_lld); + } else { + set(&mut config.lld_enabled, lld_enabled); + } + + if matches!(config.lld_mode, LldMode::SelfContained) + && !config.lld_enabled + && flags.stage.unwrap_or(0) > 0 + { + panic!( + "Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true." + ); + } + let default = debug == Some(true); config.rust_debug_assertions = debug_assertions.unwrap_or(default); config.rust_debug_assertions_std = diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index a1c9ddebb5d..2f9eaf51c34 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -185,4 +185,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: r#"The compiler profile now defaults to rust.debuginfo-level = "line-tables-only""#, }, + ChangeInfo { + change_id: 124129, + severity: ChangeSeverity::Warning, + summary: "`rust.lld` has a new default value of `true` on `x86_64-unknown-linux-gnu`. Starting at stage1, `rust-lld` will thus be this target's default linker. No config changes should be necessary.", + }, ]; diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index ff80f140482..ab95aa2e5a1 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -200,6 +200,7 @@ The following table shows known good combinations of toolchain versions. | 1.60 - 1.64 | 14 | | 1.65 - 1.69 | 15 | | 1.70 - 1.72 | 16 | -| 1.73 - 1.74 | 17 | +| 1.73 - 1.77 | 17 | +| 1.78 | 18 | Note that the compatibility policy for this feature might change in the future. diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 69fb7e3313f..3e104bdb470 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -417,6 +417,12 @@ When `rustdoc` receives this flag, it will print an extra "Version (version)" in the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation. +## `-`: load source code from the standard input + +If you specify `-` as the INPUT on the command line, then `rustdoc` will read the +source code from stdin (standard input stream) until the EOF, instead of the file +system with an otherwise specified path. + ## `@path`: load command-line flags from a path If you specify `@path` on the command-line, then it will open `path` and read diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index db3afb00369..abbd802dcdd 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -92,7 +92,7 @@ def synthetic_lookup(valobj, dict): return StdVecSyntheticProvider(valobj, dict) if rust_type == RustType.STD_VEC_DEQUE: return StdVecDequeSyntheticProvider(valobj, dict) - if rust_type == RustType.STD_SLICE: + if rust_type == RustType.STD_SLICE or rust_type == RustType.STD_STR: return StdSliceSyntheticProvider(valobj, dict) if rust_type == RustType.STD_HASH_MAP: diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index a87fd6078b8..c6330117380 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -159,6 +159,9 @@ def StdStrSummaryProvider(valobj, dict): # logger = Logger.Logger() # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName()) + # the code below assumes non-synthetic value, this makes sure the assumption holds + valobj = valobj.GetNonSyntheticValue() + length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned() if length == 0: return '""' diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index c464820413c..bccad29e0a9 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -119,7 +119,7 @@ fn synthesize_auto_trait_impl<'tcx>( attrs: Default::default(), item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, generics, trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref, ThinVec::new())), for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 8ed6ee014f3..29be3a70d54 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,7 +1,7 @@ use rustc_hir as hir; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits; -use rustc_middle::ty::{self, ToPredicate}; +use rustc_middle::ty::{self, Upcast}; use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -64,7 +64,7 @@ pub(crate) fn synthesize_blanket_impls( .instantiate(tcx, impl_args) .predicates .into_iter() - .chain(Some(ty::Binder::dummy(impl_trait_ref).to_predicate(tcx))); + .chain(Some(impl_trait_ref.upcast(tcx))); for predicate in predicates { let obligation = traits::Obligation::new( tcx, @@ -87,7 +87,7 @@ pub(crate) fn synthesize_blanket_impls( attrs: Default::default(), item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, generics: clean_ty_generics( cx, tcx.generics_of(impl_def_id), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7d8b6f34cbb..2919a4c4beb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -613,7 +613,7 @@ pub(crate) fn build_impl( did, None, clean::ImplItem(Box::new(clean::Impl { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, generics, trait_, for_, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0ab23d159a6..73737da482d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2077,7 +2077,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let generic_params = clean_bound_vars(sig.bound_vars()); BareFunction(Box::new(BareFunctionDecl { - unsafety: sig.unsafety(), + safety: sig.safety(), generic_params, decl, abi: sig.abi(), @@ -2565,7 +2565,7 @@ fn clean_bare_fn_ty<'tcx>( let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args); (generic_params, decl) }); - BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params } + BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params } } pub(crate) fn reexport_chain<'tcx>( @@ -2874,7 +2874,7 @@ fn clean_impl<'tcx>( }); let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| { let kind = ImplItem(Box::new(Impl { - unsafety: impl_.unsafety, + safety: impl_.safety, generics: clean_generics(impl_.generics, cx), trait_, for_, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index af81cc6878e..b54ec624524 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -636,17 +636,17 @@ impl Item { ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP), ty::Asyncness::No => hir::IsAsync::NotAsync, }; - hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness } + hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness } } let header = match *self.kind { ItemKind::ForeignFunctionItem(_) => { let def_id = self.def_id().unwrap(); let abi = tcx.fn_sig(def_id).skip_binder().abi(); hir::FnHeader { - unsafety: if abi == Abi::RustIntrinsic { + safety: if abi == Abi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id.expect_local()) } else { - hir::Unsafety::Unsafe + hir::Safety::Unsafe }, abi, constness: if abi == Abi::RustIntrinsic @@ -1448,8 +1448,8 @@ impl Trait { pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool { tcx.is_doc_notable_trait(self.def_id) } - pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety { - tcx.trait_def(self.def_id).unsafety + pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety { + tcx.trait_def(self.def_id).safety } pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool { tcx.check_is_object_safe(self.def_id) @@ -2344,7 +2344,7 @@ pub(crate) struct OpaqueTy { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct BareFunctionDecl { - pub(crate) unsafety: hir::Unsafety, + pub(crate) safety: hir::Safety, pub(crate) generic_params: Vec<GenericParamDef>, pub(crate) decl: FnDecl, pub(crate) abi: Abi, @@ -2446,7 +2446,7 @@ impl ConstantKind { #[derive(Clone, Debug)] pub(crate) struct Impl { - pub(crate) unsafety: hir::Unsafety, + pub(crate) safety: hir::Safety, pub(crate) generics: Generics, pub(crate) trait_: Option<Path>, pub(crate) for_: Type, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index d4468fecba4..012afada1e5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; use std::ffi::OsStr; use std::fmt; +use std::io; +use std::io::Read; +use std::path::Path; use std::path::PathBuf; use std::str::FromStr; @@ -9,14 +12,14 @@ use rustc_session::config::{ self, parse_crate_types_from_list, parse_externs, parse_target_triple, CrateType, }; use rustc_session::config::{get_cmd_lint_options, nightly_options}; -use rustc_session::config::{ - CodegenOptions, ErrorOutputType, Externs, JsonUnusedExterns, UnstableOptions, -}; +use rustc_session::config::{CodegenOptions, ErrorOutputType, Externs, Input}; +use rustc_session::config::{JsonUnusedExterns, UnstableOptions}; use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::EarlyDiagCtxt; use rustc_span::edition::Edition; +use rustc_span::FileName; use rustc_target::spec::TargetTriple; use crate::core::new_dcx; @@ -60,7 +63,7 @@ impl TryFrom<&str> for OutputFormat { pub(crate) struct Options { // Basic options / Options passed directly to rustc /// The crate root or Markdown file to load. - pub(crate) input: PathBuf, + pub(crate) input: Input, /// The name of the crate being documented. pub(crate) crate_name: Option<String>, /// Whether or not this is a bin crate @@ -179,7 +182,7 @@ impl fmt::Debug for Options { } f.debug_struct("Options") - .field("input", &self.input) + .field("input", &self.input.source_name()) .field("crate_name", &self.crate_name) .field("bin_crate", &self.bin_crate) .field("proc_macro_crate", &self.proc_macro_crate) @@ -320,6 +323,23 @@ impl RenderOptions { } } +/// Create the input (string or file path) +/// +/// Warning: Return an unrecoverable error in case of error! +fn make_input(early_dcx: &EarlyDiagCtxt, input: &str) -> Input { + if input == "-" { + let mut src = String::new(); + if io::stdin().read_to_string(&mut src).is_err() { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + early_dcx.early_fatal("couldn't read from stdin, as it did not contain valid UTF-8"); + } + Input::Str { name: FileName::anon_source_code(&src), input: src } + } else { + Input::File(PathBuf::from(input)) + } +} + impl Options { /// Parses the given command-line for options. If an error message or other early-return has /// been printed, returns `Err` with the exit code. @@ -447,15 +467,16 @@ impl Options { let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); - let input = PathBuf::from(if describe_lints { + let input = if describe_lints { "" // dummy, this won't be used - } else if matches.free.is_empty() { - dcx.fatal("missing file operand"); - } else if matches.free.len() > 1 { - dcx.fatal("too many file operands"); } else { - &matches.free[0] - }); + match matches.free.as_slice() { + [] => dcx.fatal("missing file operand"), + [input] => input, + _ => dcx.fatal("too many file operands"), + } + }; + let input = make_input(early_dcx, &input); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { @@ -792,8 +813,10 @@ impl Options { } /// Returns `true` if the file given as `self.input` is a Markdown file. - pub(crate) fn markdown_input(&self) -> bool { - self.input.extension().is_some_and(|e| e == "md" || e == "markdown") + pub(crate) fn markdown_input(&self) -> Option<&Path> { + self.input + .opt_path() + .filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown")) } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 25b78d9598d..feb03b9a823 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -32,7 +32,7 @@ use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; use crate::passes::{self, Condition::*}; -pub(crate) use rustc_session::config::{Input, Options, UnstableOptions}; +pub(crate) use rustc_session::config::{Options, UnstableOptions}; pub(crate) struct DocContext<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, @@ -204,8 +204,6 @@ pub(crate) fn create_config( // Add the doc cfg into the doc build. cfgs.push("doc".to_string()); - let input = Input::File(input); - // By default, rustdoc ignores all lints. // Specifically unblock lints relevant to documentation or the lint machinery itself. let mut lints_to_show = vec![ diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 19aa5ef949e..82f9cf1feae 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -93,8 +93,6 @@ pub(crate) fn run( dcx: &rustc_errors::DiagCtxt, options: RustdocOptions, ) -> Result<(), ErrorGuaranteed> { - let input = config::Input::File(options.input.clone()); - let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name; // See core::create_config for what's going on here. @@ -140,7 +138,7 @@ pub(crate) fn run( opts: sessopts, crate_cfg: cfgs, crate_check_cfg: options.check_cfgs.clone(), - input, + input: options.input.clone(), output_file: None, output_dir: None, file_loader: None, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 241dc37ab9c..587c464b0ed 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1013,7 +1013,7 @@ fn fmt_type<'cx>( } clean::BareFunction(ref decl) => { print_higher_ranked_params_with_space(&decl.generic_params, cx).fmt(f)?; - decl.unsafety.print_with_space().fmt(f)?; + decl.safety.print_with_space().fmt(f)?; print_abi_with_space(decl.abi).fmt(f)?; if f.alternate() { f.write_str("fn")?; @@ -1303,7 +1303,7 @@ impl clean::Impl { // Link should match `# Trait implementations` print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; - bare_fn.unsafety.print_with_space().fmt(f)?; + bare_fn.safety.print_with_space().fmt(f)?; print_abi_with_space(bare_fn.abi).fmt(f)?; let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; primitive_link_fragment( @@ -1604,11 +1604,11 @@ pub(crate) trait PrintWithSpace { fn print_with_space(&self) -> &str; } -impl PrintWithSpace for hir::Unsafety { +impl PrintWithSpace for hir::Safety { fn print_with_space(&self) -> &str { match self { - hir::Unsafety::Unsafe => "unsafe ", - hir::Unsafety::Normal => "", + hir::Safety::Unsafe => "unsafe ", + hir::Safety::Safe => "", } } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 18323e0b8ad..f3ae4b76883 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -934,7 +934,7 @@ fn assoc_method( RenderMode::ForDeref { .. } => "", }; let asyncness = header.asyncness.print_with_space(); - let unsafety = header.unsafety.print_with_space(); + let safety = header.safety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let href = assoc_href_attr(meth, link, cx); @@ -945,7 +945,7 @@ fn assoc_method( + defaultness.len() + constness.len() + asyncness.len() - + unsafety.len() + + safety.len() + abi.len() + name.as_str().len() + generics_len; @@ -964,14 +964,14 @@ fn assoc_method( w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len()); write!( w, - "{indent}{vis}{defaultness}{constness}{asyncness}{unsafety}{abi}fn \ + "{indent}{vis}{defaultness}{constness}{asyncness}{safety}{abi}fn \ <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}", indent = indent_str, vis = vis, defaultness = defaultness, constness = constness, asyncness = asyncness, - unsafety = unsafety, + safety = safety, abi = abi, href = href, name = name, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 7de2aea1c04..c7a23aa8503 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -492,7 +492,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: let unsafety_flag = match *myitem.kind { clean::FunctionItem(_) | clean::ForeignFunctionItem(_) - if myitem.fn_header(tcx).unwrap().unsafety == hir::Unsafety::Unsafe => + if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe => { "<sup title=\"unsafe function\">âš </sup>" } @@ -616,7 +616,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle let tcx = cx.tcx(); let header = it.fn_header(tcx).expect("printing a function which isn't a function"); let constness = print_constness_with_space(&header.constness, it.const_stability(tcx)); - let unsafety = header.unsafety.print_with_space(); + let safety = header.safety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let asyncness = header.asyncness.print_with_space(); let visibility = visibility_print_with_space(it, cx).to_string(); @@ -627,7 +627,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle + visibility.len() + constness.len() + asyncness.len() - + unsafety.len() + + safety.len() + abi.len() + name.as_str().len() + generics_len; @@ -638,13 +638,13 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle w.reserve(header_len); write!( w, - "{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \ + "{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", attrs = render_attributes_in_pre(it, "", cx), vis = visibility, constness = constness, asyncness = asyncness, - unsafety = unsafety, + safety = safety, abi = abi, name = name, generics = f.generics.print(cx), @@ -674,10 +674,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: wrap_item(w, |mut w| { write!( w, - "{attrs}{vis}{unsafety}{is_auto}trait {name}{generics}{bounds}", + "{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}", attrs = render_attributes_in_pre(it, "", cx), vis = visibility_print_with_space(it, cx), - unsafety = t.unsafety(tcx).print_with_space(), + safety = t.safety(tcx).print_with_space(), is_auto = if t.is_auto(tcx) { "auto " } else { "" }, name = it.name.unwrap(), generics = t.generics.print(cx), diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 35b99ab46f0..f856b4e9f16 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -619,10 +619,10 @@ impl FromWithTcx<clean::Term> for Term { impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer { fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { - let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl; + let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl; FunctionPointer { header: Header { - unsafe_: matches!(unsafety, rustc_hir::Unsafety::Unsafe), + unsafe_: matches!(safety, rustc_hir::Safety::Unsafe), const_: false, async_: false, abi: convert_abi(abi), @@ -651,7 +651,7 @@ impl FromWithTcx<clean::FnDecl> for FnDecl { impl FromWithTcx<clean::Trait> for Trait { fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self { let is_auto = trait_.is_auto(tcx); - let is_unsafe = trait_.unsafety(tcx) == rustc_hir::Unsafety::Unsafe; + let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe; let is_object_safe = trait_.is_object_safe(tcx); let clean::Trait { items, generics, bounds, .. } = trait_; Trait { @@ -678,7 +678,7 @@ impl FromWithTcx<clean::PolyTrait> for PolyTrait { impl FromWithTcx<clean::Impl> for Impl { fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let provided_trait_methods = impl_.provided_trait_methods(tcx); - let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_; + let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: use something like ImplKind in JSON? let (synthetic, blanket_impl) = match kind { clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None), @@ -690,7 +690,7 @@ impl FromWithTcx<clean::Impl> for Impl { ty::ImplPolarity::Negative => true, }; Impl { - is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, + is_unsafe: safety == rustc_hir::Safety::Unsafe, generics: generics.into_tcx(tcx), provided_trait_methods: provided_trait_methods .into_iter() diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f2a7518b4ce..0650afb90c7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -730,10 +730,10 @@ fn main_args( core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts); match (options.should_test, options.markdown_input()) { - (true, true) => return wrap_return(&diag, markdown::test(options)), - (true, false) => return doctest::run(&diag, options), - (false, true) => { - let input = options.input.clone(); + (true, Some(_)) => return wrap_return(&diag, markdown::test(options)), + (true, None) => return doctest::run(&diag, options), + (false, Some(input)) => { + let input = input.to_owned(); let edition = options.edition; let config = core::create_config(options, &render_options, using_internal_features); @@ -747,7 +747,7 @@ fn main_args( }), ); } - (false, false) => {} + (false, None) => {} } // need to move these items separately because we lose them by the time the closure is called, diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index dcd2cf02a30..7289ed56dc7 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -144,8 +144,14 @@ pub(crate) fn render<P: AsRef<Path>>( /// Runs any tests/code examples in the markdown file `input`. pub(crate) fn test(options: Options) -> Result<(), String> { - let input_str = read_to_string(&options.input) - .map_err(|err| format!("{input}: {err}", input = options.input.display()))?; + use rustc_session::config::Input; + let input_str = match &options.input { + Input::File(path) => { + read_to_string(&path).map_err(|err| format!("{}: {err}", path.display()))? + } + Input::Str { name: _, input } => input.clone(), + }; + let mut opts = GlobalTestOptions::default(); opts.no_crate_inject = true; @@ -155,12 +161,12 @@ pub(crate) fn test(options: Options) -> Result<(), String> { generate_args_file(&file_path, &options)?; let mut collector = Collector::new( - options.input.display().to_string(), + options.input.filestem().to_string(), options.clone(), true, opts, None, - Some(options.input), + options.input.opt_path().map(ToOwned::to_owned), options.enable_per_target_ignores, file_path, ); diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index e788069ea80..1c5a6dcfb1f 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -188,7 +188,19 @@ pub enum TypeBindingKind { Constraint(Vec<GenericBound>), } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +/// An opaque identifier for an item. +/// +/// It can be used to lookup in [Crate::index] or [Crate::paths] to resolve it +/// to an [Item]. +/// +/// Id's are only valid within a single JSON blob. They cannot be used to +/// resolve references between the JSON output's for different crates. +/// +/// Rustdoc makes no guarantees about the inner value of Id's. Applications +/// should treat them as opaque keys to lookup items, and avoid attempting +/// to parse them, or otherwise depend on any implementation details. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +// FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types. pub struct Id(pub String); #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 4de0094ac78743d2c8ff682489e35c8a7cafe8e +Subproject 0de7f2ec6c39d68022e6b97a39559d2f4dbf393 diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 9662c8f4fe2..2a644922fb1 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -5,13 +5,13 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor}; use rustc_hir::{ - self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource, Unsafety, + self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Safety, Impl, Item, ItemKind, UnsafeSource, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt, + self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, Upcast, TraitPredicate, Ty, TyCtxt, }; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; @@ -415,7 +415,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } if let Some(header) = kind.header() - && header.unsafety == Unsafety::Unsafe + && header.safety == Safety::Unsafe { self.has_unsafe = true; } @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), polarity: ty::PredicatePolarity::Positive, }) - .to_predicate(tcx) + .upcast(tcx) }), )), Reveal::UserFacing, diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs index f935ae2e3e4..36ba19698c7 100644 --- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs +++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{is_doc_hidden, return_ty}; -use rustc_hir::{BodyId, FnSig, OwnerId, Unsafety}; +use rustc_hir::{BodyId, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::{sym, Span}; @@ -33,14 +33,14 @@ pub fn check( } let span = cx.tcx.def_span(owner_id); - match (headers.safety, sig.header.unsafety) { - (false, Unsafety::Unsafe) => span_lint( + match (headers.safety, sig.header.safety) { + (false, Safety::Unsafe) => span_lint( cx, MISSING_SAFETY_DOC, span, "unsafe function's docs miss `# Safety` section", ), - (true, Unsafety::Normal) => span_lint( + (true, Safety::Safe) => span_lint( cx, UNNECESSARY_SAFETY_DOC, span, diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 4bced104d3b..7fdb582e640 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -12,7 +12,7 @@ use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, TraitItemKind, Unsafety}; +use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -415,13 +415,13 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { } }, ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { - (false, Unsafety::Unsafe) => span_lint( + (false, Safety::Unsafe) => span_lint( cx, MISSING_SAFETY_DOC, cx.tcx.def_span(item.owner_id), "docs for unsafe trait missing `# Safety` section", ), - (true, Unsafety::Normal) => span_lint( + (true, Safety::Safe) => span_lint( cx, UNNECESSARY_SAFETY_DOC, cx.tcx.def_span(item.owner_id), diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 306a4a9e55c..b58018ca035 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; -use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety}; +use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ @@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { ty::FnPtr(sig) => sig.skip_binder(), ty::Closure(_, subs) => cx .tcx - .signature_unclosure(subs.as_closure().sig(), Unsafety::Normal) + .signature_unclosure(subs.as_closure().sig(), Safety::Safe) .skip_binder(), _ => { if typeck.type_dependent_def_id(body.value.hir_id).is_some() @@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { && let output = typeck.expr_ty(body.value) && let ty::Tuple(tys) = *subs.type_at(1).kind() { - cx.tcx.mk_fn_sig(tys, output, false, Unsafety::Normal, Abi::Rust) + cx.tcx.mk_fn_sig(tys, output, false, Safety::Safe, Abi::Rust) } else { return; } @@ -241,11 +241,9 @@ fn check_inputs( } fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: FnSig<'_>) -> bool { - call_sig.unsafety == Unsafety::Normal + call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions( - cx.tcx - .signature_unclosure(closure.sig(), Unsafety::Normal) - .skip_binder(), + cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder(), call_sig, ) } diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs index 8ac17e17688..7729c556e1f 100644 --- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs +++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety}; +use rustc_hir::{Body, ExprKind, FnDecl, Safety, ImplicitSelfKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -34,7 +34,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: ImplicitSelfKind::None => return, }; - let name = if sig.header.unsafety == Unsafety::Unsafe { + let name = if sig.header.safety == Safety::Unsafe { name.strip_suffix("_unchecked").unwrap_or(name) } else { name diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 995dd782cbb..b44a5f20ef6 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -19,30 +19,30 @@ pub(super) fn check_fn<'tcx>( body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - let unsafety = match kind { - intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety, - intravisit::FnKind::Method(_, sig) => sig.header.unsafety, + let safety = match kind { + intravisit::FnKind::ItemFn(_, _, hir::FnHeader { safety, .. }) => safety, + intravisit::FnKind::Method(_, sig) => sig.header.safety, intravisit::FnKind::Closure => return, }; - check_raw_ptr(cx, unsafety, decl, body, def_id); + check_raw_ptr(cx, safety, decl, body, def_id); } pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { let body = cx.tcx.hir().body(eid); - check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id); + check_raw_ptr(cx, sig.header.safety, sig.decl, body, item.owner_id.def_id); } } fn check_raw_ptr<'tcx>( cx: &LateContext<'tcx>, - unsafety: hir::Unsafety, + safety: hir::Safety, decl: &'tcx hir::FnDecl<'tcx>, body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) { + if safety == hir::Safety::Safe && cx.effective_visibilities.is_exported(def_id) { let raw_ptrs = iter_input_pats(decl, body) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::<HirIdSet>(); @@ -58,7 +58,7 @@ fn check_raw_ptr<'tcx>( }, hir::ExprKind::MethodCall(_, recv, args, _) => { let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap(); - if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().unsafety == hir::Unsafety::Unsafe { + if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety == hir::Safety::Unsafe { check_arg(cx, &raw_ptrs, recv); for arg in args { check_arg(cx, &raw_ptrs, arg); diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index 157f6105984..9aedf5ec7e8 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; -use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Unsafety}; +use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Safety}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // #11201 && let header = signature.header - && header.unsafety == Unsafety::Normal + && header.safety == Safety::Safe && header.abi == Abi::Rust && impl_item.ident.name == sym::to_string && let decl = signature.decl diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 63545d6c503..2b92bff016d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -5038,7 +5038,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr } const FN_HEADER: hir::FnHeader = hir::FnHeader { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, abi: rustc_target::spec::abi::Abi::Rust, @@ -5214,7 +5214,5 @@ impl OutType { } fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool { - expected.constness == actual.constness - && expected.unsafety == actual.unsafety - && expected.asyncness == actual.asyncness + expected.constness == actual.constness && expected.safety == actual.safety && expected.asyncness == actual.asyncness } diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 0e138066780..5306205aed7 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::{for_each_expr_with_closures, Descend, Visitable}; use core::ops::ControlFlow::Continue; use hir::def::{DefKind, Res}; -use hir::{BlockCheckMode, ExprKind, QPath, UnOp, Unsafety}; +use hir::{BlockCheckMode, ExprKind, Safety, QPath, UnOp}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -133,7 +133,7 @@ fn collect_unsafe_exprs<'tcx>( ty::FnPtr(sig) => sig, _ => return Continue(Descend::Yes), }; - if sig.unsafety() == Unsafety::Unsafe { + if sig.safety() == Safety::Unsafe { unsafe_ops.push(("unsafe function call occurs here", expr.span)); } }, @@ -144,7 +144,7 @@ fn collect_unsafe_exprs<'tcx>( .type_dependent_def_id(expr.hir_id) .map(|def_id| cx.tcx.fn_sig(def_id)) { - if sig.skip_binder().unsafety() == Unsafety::Unsafe { + if sig.skip_binder().safety() == Safety::Unsafe { unsafe_ops.push(("unsafe method call occurs here", expr.span)); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 78dd1e05162..b60fea3f03e 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { let name = impl_item.ident.name; let id = impl_item.owner_id; - if sig.header.unsafety == hir::Unsafety::Unsafe { + if sig.header.safety == hir::Safety::Unsafe { // can't be implemented for unsafe new return; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 2534e3c8468..65929cd5fea 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -12,7 +12,7 @@ use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{ self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind, - ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, + ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -542,7 +542,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio if let Some(args) = args && !args.is_empty() && body.map_or(true, |body| { - sig.header.unsafety == Unsafety::Unsafe || contains_unsafe_block(cx, body.value) + sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value) }) { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index cbd16180077..4120bb1331b 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => { + (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety == hir::Safety::Unsafe => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => { + (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety == hir::Safety::Safe => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index d3bbc66bcae..d4a5f547211 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -386,21 +386,21 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ( Trait(box ast::Trait { is_auto: la, - unsafety: lu, + safety: lu, generics: lg, bounds: lb, items: li, }), Trait(box ast::Trait { is_auto: ra, - unsafety: ru, + safety: ru, generics: rg, bounds: rb, items: ri, }), ) => { la == ra - && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) @@ -408,7 +408,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), ( Impl(box ast::Impl { - unsafety: lu, + safety: lu, polarity: lp, defaultness: ld, constness: lc, @@ -418,7 +418,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: li, }), Impl(box ast::Impl { - unsafety: ru, + safety: ru, polarity: rp, defaultness: rd, constness: rc, @@ -428,7 +428,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: ri, }), ) => { - matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + matches!(lu, Safety::Default) == matches!(ru, Safety::Default) && matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive) && eq_defaultness(*ld, *rd) && matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) @@ -605,7 +605,7 @@ fn eq_opt_coroutine_kind(l: Option<CoroutineKind>, r: Option<CoroutineKind>) -> } pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { - matches!(l.unsafety, Unsafe::No) == matches!(r.unsafety, Unsafe::No) + matches!(l.safety, Safety::Default) == matches!(r.safety, Safety::Default) && eq_opt_coroutine_kind(l.coroutine_kind, r.coroutine_kind) && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) && eq_ext(&l.ext, &r.ext) @@ -712,7 +712,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, (BareFn(l), BareFn(r)) => { - l.unsafety == r.unsafety + l.safety == r.safety && eq_ext(&l.ext, &r.ext) && over(&l.generic_params, &r.generic_params, eq_generic_param) && eq_fn_decl(&l.decl, &r.decl) diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 42267310513..553e8999975 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -18,8 +18,8 @@ use rustc_ast::AttrStyle; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, - ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, - TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, Safety, TraitItem, + TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -207,10 +207,9 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), - ItemKind::Trait(_, Unsafety::Unsafe, ..) + ItemKind::Trait(_, Safety::Unsafe, ..) | ItemKind::Impl(Impl { - unsafety: Unsafety::Unsafe, - .. + safety: Safety::Unsafe, .. }) => (Pat::Str("unsafe"), Pat::Str("}")), ItemKind::Trait(IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), @@ -323,7 +322,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::BareFn(bare_fn) => ( - if bare_fn.unsafety == Unsafety::Unsafe { + if bare_fn.safety == Safety::Unsafe { Pat::Str("unsafe") } else if bare_fn.abi != Abi::Rust { Pat::Str("extern") diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c921168df29..9f285621e0c 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { mut_ty.mutbl.hash(&mut self.s); }, TyKind::BareFn(bfn) => { - bfn.unsafety.hash(&mut self.s); + bfn.safety.hash(&mut self.s); bfn.abi.hash(&mut self.s); for arg in bfn.decl.inputs { self.hash_ty(arg); diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index e3ab42c3107..c29e3feac9a 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; +use rustc_hir::{Expr, FnDecl, Safety, LangItem, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::interpret::Scalar; @@ -18,7 +18,7 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, - GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, ToPredicate, TraitRef, Ty, TyCtxt, + GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, Upcast, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; @@ -311,7 +311,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( cause: ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: Binder::dummy(trait_ref).to_predicate(tcx), + predicate: trait_ref.upcast(tcx), }; infcx .evaluate_obligation(&obligation) @@ -562,7 +562,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, + ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, _ => false, } } diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index a3f3b32ed37..90b56297bb5 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -6,7 +6,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; use rustc_hir::{ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, - Stmt, UnOp, UnsafeSource, Unsafety, + Safety, Stmt, UnOp, UnsafeSource, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -421,16 +421,16 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .typeck_results() .type_dependent_def_id(e.hir_id) .map_or(false, |id| { - self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe + self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe }) => { self.is_unsafe = true; }, ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() { - ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe => { + ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { self.is_unsafe = true; }, - ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true, + ty::FnPtr(sig) if sig.safety() == Safety::Unsafe => self.is_unsafe = true, _ => walk_expr(self, e), }, ExprKind::Path(ref p) @@ -452,7 +452,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { } fn visit_nested_item(&mut self, id: ItemId) { if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind { - self.is_unsafe = i.unsafety == Unsafety::Unsafe; + self.is_unsafe = i.safety == Safety::Unsafe; } } } diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index d034826a830..f581204d5f1 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -64,6 +64,12 @@ impl Rustc { self } + /// Specify a specific optimization level. + pub fn opt_level(&mut self, option: &str) -> &mut Self { + self.cmd.arg(format!("-Copt-level={option}")); + self + } + /// Specify type(s) of output files to generate. pub fn emit(&mut self, kinds: &str) -> &mut Self { self.cmd.arg(format!("--emit={kinds}")); diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 90e9e58ef9c..e869787b394 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -247,7 +247,7 @@ fn allow_single_line_let_else_block(result: &str, block: &ast::Block) -> bool { #[allow(dead_code)] #[derive(Debug)] struct Item<'a> { - unsafety: ast::Unsafe, + safety: ast::Safety, abi: Cow<'static, str>, vis: Option<&'a ast::Visibility>, body: Vec<BodyElement<'a>>, @@ -257,7 +257,7 @@ struct Item<'a> { impl<'a> Item<'a> { fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { Item { - unsafety: fm.unsafety, + safety: fm.safety, abi: format_extern( ast::Extern::from_abi(fm.abi, DUMMY_SP), config.force_explicit_abi(), @@ -290,7 +290,7 @@ pub(crate) struct FnSig<'a> { coroutine_kind: Cow<'a, Option<ast::CoroutineKind>>, constness: ast::Const, defaultness: ast::Defaultness, - unsafety: ast::Unsafe, + safety: ast::Safety, visibility: &'a ast::Visibility, } @@ -301,7 +301,7 @@ impl<'a> FnSig<'a> { visibility: &'a ast::Visibility, ) -> FnSig<'a> { FnSig { - unsafety: method_sig.header.unsafety, + safety: method_sig.header.safety, coroutine_kind: Cow::Borrowed(&method_sig.header.coroutine_kind), constness: method_sig.header.constness, defaultness: ast::Defaultness::Final, @@ -330,7 +330,7 @@ impl<'a> FnSig<'a> { constness: fn_sig.header.constness, coroutine_kind: Cow::Borrowed(&fn_sig.header.coroutine_kind), defaultness, - unsafety: fn_sig.header.unsafety, + safety: fn_sig.header.safety, visibility: vis, }, _ => unreachable!(), @@ -345,7 +345,7 @@ impl<'a> FnSig<'a> { result.push_str(format_constness(self.constness)); self.coroutine_kind .map(|coroutine_kind| result.push_str(format_coro(&coroutine_kind))); - result.push_str(format_unsafety(self.unsafety)); + result.push_str(format_safety(self.safety)); result.push_str(&format_extern( self.ext, context.config.force_explicit_abi(), @@ -356,7 +356,7 @@ impl<'a> FnSig<'a> { impl<'a> FmtVisitor<'a> { fn format_item(&mut self, item: &Item<'_>) { - self.buffer.push_str(format_unsafety(item.unsafety)); + self.buffer.push_str(format_safety(item.safety)); self.buffer.push_str(&item.abi); let snippet = self.snippet(item.span); @@ -924,7 +924,7 @@ fn format_impl_ref_and_type( offset: Indent, ) -> Option<String> { let ast::Impl { - unsafety, + safety, polarity, defaultness, constness, @@ -937,7 +937,7 @@ fn format_impl_ref_and_type( result.push_str(&format_visibility(context, &item.vis)); result.push_str(format_defaultness(defaultness)); - result.push_str(format_unsafety(unsafety)); + result.push_str(format_safety(safety)); let shape = if context.config.version() == Version::Two { Shape::indented(offset + last_line_width(&result), context.config) @@ -1137,7 +1137,7 @@ pub(crate) fn format_trait( }; let ast::Trait { is_auto, - unsafety, + safety, ref generics, ref bounds, ref items, @@ -1147,7 +1147,7 @@ pub(crate) fn format_trait( let header = format!( "{}{}{}trait ", format_visibility(context, &item.vis), - format_unsafety(unsafety), + format_safety(safety), format_auto(is_auto), ); result.push_str(&header); diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index fe2d28ae1b9..75dea90d994 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -899,7 +899,7 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(crate::utils::format_unsafety(bare_fn.unsafety)); + result.push_str(crate::utils::format_safety(bare_fn.safety)); result.push_str(&format_extern( bare_fn.ext, diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index b91d9b47cb6..09e1dbde1d0 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -108,10 +108,10 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str } #[inline] -pub(crate) fn format_unsafety(unsafety: ast::Unsafe) -> &'static str { +pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str { match unsafety { - ast::Unsafe::Yes(..) => "unsafe ", - ast::Unsafe::No => "", + ast::Safety::Unsafe(..) => "unsafe ", + ast::Safety::Default => "", } } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index e1c7dc35087..7a0c68c214c 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -24,7 +24,7 @@ use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes, + self, contains_skip, count_newlines, depr_skip_annotation, format_safety, inner_attributes, last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -517,9 +517,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_enum(item.ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(unsafety, ref mod_kind) => { + ast::ItemKind::Mod(safety, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs); + self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -913,7 +913,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn format_mod( &mut self, mod_kind: &ast::ModKind, - unsafety: ast::Unsafe, + safety: ast::Safety, vis: &ast::Visibility, s: Span, ident: symbol::Ident, @@ -921,7 +921,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) { let vis_str = utils::format_visibility(&self.get_context(), vis); self.push_str(&*vis_str); - self.push_str(format_unsafety(unsafety)); + self.push_str(format_safety(safety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 1a3d6f8d813..d1ae24007b3 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -103,7 +103,6 @@ run-make/issue-25581/Makefile run-make/issue-26006/Makefile run-make/issue-26092/Makefile run-make/issue-28595/Makefile -run-make/issue-28766/Makefile run-make/issue-30063/Makefile run-make/issue-33329/Makefile run-make/issue-35164/Makefile @@ -128,7 +127,6 @@ run-make/issue-85401-static-mir/Makefile run-make/issue-85441/Makefile run-make/issue-88756-default-output/Makefile run-make/issue-97463-abi-param-passing/Makefile -run-make/issue64319/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile @@ -236,10 +234,8 @@ run-make/rlib-format-packed-bundled-libs/Makefile run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile run-make/rustdoc-io-error/Makefile -run-make/rustdoc-scrape-examples-invalid-expr/Makefile run-make/rustdoc-scrape-examples-macros/Makefile run-make/rustdoc-scrape-examples-multiple/Makefile -run-make/rustdoc-scrape-examples-remap/Makefile run-make/rustdoc-scrape-examples-test/Makefile run-make/rustdoc-scrape-examples-whitespace/Makefile run-make/rustdoc-verify-output-files/Makefile @@ -264,7 +260,6 @@ run-make/stable-symbol-names/Makefile run-make/static-dylib-by-default/Makefile run-make/static-extern-type/Makefile run-make/static-pie/Makefile -run-make/static-unwinding/Makefile run-make/staticlib-blank-lib/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/std-core-cycle/Makefile diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index a931782e8cc..6b8106bbc21 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2915,7 +2915,6 @@ ui/macros/issue-95267.rs ui/macros/issue-95533.rs ui/macros/issue-98466-allow.rs ui/macros/issue-98466.rs -ui/macros/issue-98790.rs ui/macros/issue-99261.rs ui/macros/issue-99265.rs ui/macros/issue-99907.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 94a0eee154d..6e92dab1abc 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -41,6 +41,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/macros/not-utf8.bin", // testing including data with the include macros "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include "tests/ui/proc-macro/auxiliary/included-file.txt", // more include + "tests/ui/unpretty/auxiliary/data.txt", // more include "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer "tests/ui/sanitizer/dataflow-abilist.txt", // dataflow sanitizer ABI list file "tests/ui/shell-argfiles/shell-argfiles.args", // passing args via a file diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs index 97d545e0283..32c5be1ec65 100644 --- a/tests/codegen/float/f128.rs +++ b/tests/codegen/float/f128.rs @@ -2,6 +2,7 @@ #![crate_type = "lib"] #![feature(f128)] +#![feature(f16)] #![feature(core_intrinsics)] // CHECK-LABEL: i1 @f128_eq( @@ -127,3 +128,196 @@ pub fn f128_rem_assign(a: &mut f128, b: f128) { // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} *a %= b } + +/* float to float conversions */ + +// CHECK-LABEL: half @f128_as_f16( +#[no_mangle] +pub fn f128_as_f16(a: f128) -> f16 { + // CHECK: fptrunc fp128 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: float @f128_as_f32( +#[no_mangle] +pub fn f128_as_f32(a: f128) -> f32 { + // CHECK: fptrunc fp128 %{{.+}} to float + a as f32 +} + +// CHECK-LABEL: double @f128_as_f64( +#[no_mangle] +pub fn f128_as_f64(a: f128) -> f64 { + // CHECK: fptrunc fp128 %{{.+}} to double + a as f64 +} + +// CHECK-LABEL: fp128 @f128_as_self( +#[no_mangle] +pub fn f128_as_self(a: f128) -> f128 { + // CHECK: ret fp128 %{{.+}} + a as f128 +} + +// CHECK-LABEL: fp128 @f16_as_f128( +#[no_mangle] +pub fn f16_as_f128(a: f16) -> f128 { + // CHECK: fpext half %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @f32_as_f128( +#[no_mangle] +pub fn f32_as_f128(a: f32) -> f128 { + // CHECK: fpext float %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @f64_as_f128( +#[no_mangle] +pub fn f64_as_f128(a: f64) -> f128 { + // CHECK: fpext double %{{.+}} to fp128 + a as f128 +} + +/* float to int conversions */ + +// CHECK-LABEL: i8 @f128_as_u8( +#[no_mangle] +pub fn f128_as_u8(a: f128) -> u8 { + // CHECK: call i8 @llvm.fptoui.sat.i8.f128(fp128 %{{.+}}) + a as u8 +} + +#[no_mangle] +pub fn f128_as_u16(a: f128) -> u16 { + // CHECK: call i16 @llvm.fptoui.sat.i16.f128(fp128 %{{.+}}) + a as u16 +} + +// CHECK-LABEL: i32 @f128_as_u32( +#[no_mangle] +pub fn f128_as_u32(a: f128) -> u32 { + // CHECK: call i32 @llvm.fptoui.sat.i32.f128(fp128 %{{.+}}) + a as u32 +} + +// CHECK-LABEL: i64 @f128_as_u64( +#[no_mangle] +pub fn f128_as_u64(a: f128) -> u64 { + // CHECK: call i64 @llvm.fptoui.sat.i64.f128(fp128 %{{.+}}) + a as u64 +} + +// CHECK-LABEL: i128 @f128_as_u128( +#[no_mangle] +pub fn f128_as_u128(a: f128) -> u128 { + // CHECK: call i128 @llvm.fptoui.sat.i128.f128(fp128 %{{.+}}) + a as u128 +} + +// CHECK-LABEL: i8 @f128_as_i8( +#[no_mangle] +pub fn f128_as_i8(a: f128) -> i8 { + // CHECK: call i8 @llvm.fptosi.sat.i8.f128(fp128 %{{.+}}) + a as i8 +} + +// CHECK-LABEL: i16 @f128_as_i16( +#[no_mangle] +pub fn f128_as_i16(a: f128) -> i16 { + // CHECK: call i16 @llvm.fptosi.sat.i16.f128(fp128 %{{.+}}) + a as i16 +} +// CHECK-LABEL: i32 @f128_as_i32( +#[no_mangle] +pub fn f128_as_i32(a: f128) -> i32 { + // CHECK: call i32 @llvm.fptosi.sat.i32.f128(fp128 %{{.+}}) + a as i32 +} + +// CHECK-LABEL: i64 @f128_as_i64( +#[no_mangle] +pub fn f128_as_i64(a: f128) -> i64 { + // CHECK: call i64 @llvm.fptosi.sat.i64.f128(fp128 %{{.+}}) + a as i64 +} + +// CHECK-LABEL: i128 @f128_as_i128( +#[no_mangle] +pub fn f128_as_i128(a: f128) -> i128 { + // CHECK: call i128 @llvm.fptosi.sat.i128.f128(fp128 %{{.+}}) + a as i128 +} + +/* int to float conversions */ + +// CHECK-LABEL: fp128 @u8_as_f128( +#[no_mangle] +pub fn u8_as_f128(a: u8) -> f128 { + // CHECK: uitofp i8 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @u16_as_f128( +#[no_mangle] +pub fn u16_as_f128(a: u16) -> f128 { + // CHECK: uitofp i16 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @u32_as_f128( +#[no_mangle] +pub fn u32_as_f128(a: u32) -> f128 { + // CHECK: uitofp i32 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @u64_as_f128( +#[no_mangle] +pub fn u64_as_f128(a: u64) -> f128 { + // CHECK: uitofp i64 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @u128_as_f128( +#[no_mangle] +pub fn u128_as_f128(a: u128) -> f128 { + // CHECK: uitofp i128 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @i8_as_f128( +#[no_mangle] +pub fn i8_as_f128(a: i8) -> f128 { + // CHECK: sitofp i8 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @i16_as_f128( +#[no_mangle] +pub fn i16_as_f128(a: i16) -> f128 { + // CHECK: sitofp i16 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @i32_as_f128( +#[no_mangle] +pub fn i32_as_f128(a: i32) -> f128 { + // CHECK: sitofp i32 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @i64_as_f128( +#[no_mangle] +pub fn i64_as_f128(a: i64) -> f128 { + // CHECK: sitofp i64 %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: fp128 @i128_as_f128( +#[no_mangle] +pub fn i128_as_f128(a: i128) -> f128 { + // CHECK: sitofp i128 %{{.+}} to fp128 + a as f128 +} diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs index d1f75cc3b68..96daac869c2 100644 --- a/tests/codegen/float/f16.rs +++ b/tests/codegen/float/f16.rs @@ -1,9 +1,12 @@ // Verify that our intrinsics generate the correct LLVM calls for f16 #![crate_type = "lib"] +#![feature(f128)] #![feature(f16)] #![feature(core_intrinsics)] +/* arithmetic */ + // CHECK-LABEL: i1 @f16_eq( #[no_mangle] pub fn f16_eq(a: f16, b: f16) -> bool { @@ -109,7 +112,7 @@ pub fn f16_sub_assign(a: &mut f16, b: f16) { pub fn f16_mul_assign(a: &mut f16, b: f16) { // CHECK: fmul half %{{.+}}, %{{.+}} // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} - *a *= b + *a *= b; } // CHECK-LABEL: void @f16_div_assign( @@ -117,7 +120,7 @@ pub fn f16_mul_assign(a: &mut f16, b: f16) { pub fn f16_div_assign(a: &mut f16, b: f16) { // CHECK: fdiv half %{{.+}}, %{{.+}} // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} - *a /= b + *a /= b; } // CHECK-LABEL: void @f16_rem_assign( @@ -125,5 +128,198 @@ pub fn f16_div_assign(a: &mut f16, b: f16) { pub fn f16_rem_assign(a: &mut f16, b: f16) { // CHECK: frem half %{{.+}}, %{{.+}} // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} - *a %= b + *a %= b; +} + +/* float to float conversions */ + +// CHECK-LABEL: half @f16_as_self( +#[no_mangle] +pub fn f16_as_self(a: f16) -> f16 { + // CHECK: ret half %{{.+}} + a as f16 +} + +// CHECK-LABEL: float @f16_as_f32( +#[no_mangle] +pub fn f16_as_f32(a: f16) -> f32 { + // CHECK: fpext half %{{.+}} to float + a as f32 +} + +// CHECK-LABEL: double @f16_as_f64( +#[no_mangle] +pub fn f16_as_f64(a: f16) -> f64 { + // CHECK: fpext half %{{.+}} to double + a as f64 +} + +// CHECK-LABEL: fp128 @f16_as_f128( +#[no_mangle] +pub fn f16_as_f128(a: f16) -> f128 { + // CHECK: fpext half %{{.+}} to fp128 + a as f128 +} + +// CHECK-LABEL: half @f32_as_f16( +#[no_mangle] +pub fn f32_as_f16(a: f32) -> f16 { + // CHECK: fptrunc float %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @f64_as_f16( +#[no_mangle] +pub fn f64_as_f16(a: f64) -> f16 { + // CHECK: fptrunc double %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @f128_as_f16( +#[no_mangle] +pub fn f128_as_f16(a: f128) -> f16 { + // CHECK: fptrunc fp128 %{{.+}} to half + a as f16 +} + +/* float to int conversions */ + +// CHECK-LABEL: i8 @f16_as_u8( +#[no_mangle] +pub fn f16_as_u8(a: f16) -> u8 { + // CHECK: call i8 @llvm.fptoui.sat.i8.f16(half %{{.+}}) + a as u8 +} + +#[no_mangle] +pub fn f16_as_u16(a: f16) -> u16 { + // CHECK: call i16 @llvm.fptoui.sat.i16.f16(half %{{.+}}) + a as u16 +} + +// CHECK-LABEL: i32 @f16_as_u32( +#[no_mangle] +pub fn f16_as_u32(a: f16) -> u32 { + // CHECK: call i32 @llvm.fptoui.sat.i32.f16(half %{{.+}}) + a as u32 +} + +// CHECK-LABEL: i64 @f16_as_u64( +#[no_mangle] +pub fn f16_as_u64(a: f16) -> u64 { + // CHECK: call i64 @llvm.fptoui.sat.i64.f16(half %{{.+}}) + a as u64 +} + +// CHECK-LABEL: i128 @f16_as_u128( +#[no_mangle] +pub fn f16_as_u128(a: f16) -> u128 { + // CHECK: call i128 @llvm.fptoui.sat.i128.f16(half %{{.+}}) + a as u128 +} + +// CHECK-LABEL: i8 @f16_as_i8( +#[no_mangle] +pub fn f16_as_i8(a: f16) -> i8 { + // CHECK: call i8 @llvm.fptosi.sat.i8.f16(half %{{.+}}) + a as i8 +} + +// CHECK-LABEL: i16 @f16_as_i16( +#[no_mangle] +pub fn f16_as_i16(a: f16) -> i16 { + // CHECK: call i16 @llvm.fptosi.sat.i16.f16(half %{{.+}}) + a as i16 +} +// CHECK-LABEL: i32 @f16_as_i32( +#[no_mangle] +pub fn f16_as_i32(a: f16) -> i32 { + // CHECK: call i32 @llvm.fptosi.sat.i32.f16(half %{{.+}}) + a as i32 +} + +// CHECK-LABEL: i64 @f16_as_i64( +#[no_mangle] +pub fn f16_as_i64(a: f16) -> i64 { + // CHECK: call i64 @llvm.fptosi.sat.i64.f16(half %{{.+}}) + a as i64 +} + +// CHECK-LABEL: i128 @f16_as_i128( +#[no_mangle] +pub fn f16_as_i128(a: f16) -> i128 { + // CHECK: call i128 @llvm.fptosi.sat.i128.f16(half %{{.+}}) + a as i128 +} + +/* int to float conversions */ + +// CHECK-LABEL: half @u8_as_f16( +#[no_mangle] +pub fn u8_as_f16(a: u8) -> f16 { + // CHECK: uitofp i8 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @u16_as_f16( +#[no_mangle] +pub fn u16_as_f16(a: u16) -> f16 { + // CHECK: uitofp i16 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @u32_as_f16( +#[no_mangle] +pub fn u32_as_f16(a: u32) -> f16 { + // CHECK: uitofp i32 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @u64_as_f16( +#[no_mangle] +pub fn u64_as_f16(a: u64) -> f16 { + // CHECK: uitofp i64 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @u128_as_f16( +#[no_mangle] +pub fn u128_as_f16(a: u128) -> f16 { + // CHECK: uitofp i128 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @i8_as_f16( +#[no_mangle] +pub fn i8_as_f16(a: i8) -> f16 { + // CHECK: sitofp i8 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @i16_as_f16( +#[no_mangle] +pub fn i16_as_f16(a: i16) -> f16 { + // CHECK: sitofp i16 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @i32_as_f16( +#[no_mangle] +pub fn i32_as_f16(a: i32) -> f16 { + // CHECK: sitofp i32 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @i64_as_f16( +#[no_mangle] +pub fn i64_as_f16(a: i64) -> f16 { + // CHECK: sitofp i64 %{{.+}} to half + a as f16 +} + +// CHECK-LABEL: half @i128_as_f16( +#[no_mangle] +pub fn i128_as_f16(a: i128) -> f16 { + // CHECK: sitofp i128 %{{.+}} to half + a as f16 } diff --git a/tests/codegen/intrinsics/aggregate-thin-pointer.rs b/tests/codegen/intrinsics/aggregate-thin-pointer.rs new file mode 100644 index 00000000000..aa3bf7e8b14 --- /dev/null +++ b/tests/codegen/intrinsics/aggregate-thin-pointer.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -O -C no-prepopulate-passes -Z mir-enable-passes=-InstSimplify +//@ only-64bit (so I don't need to worry about usize) + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::aggregate_raw_ptr; + +// InstSimplify replaces these with casts if it can, which means they're almost +// never seen in codegen, but PR#121571 found a way, so add a test for it. + +#[inline(never)] +pub fn opaque(_p: &*const i32) {} + +// CHECK-LABEL: @thin_ptr_via_aggregate( +#[no_mangle] +pub unsafe fn thin_ptr_via_aggregate(p: *const ()) { + // CHECK: %mem = alloca + // CHECK: store ptr %p, ptr %mem + // CHECK: call {{.+}}aggregate_thin_pointer{{.+}} %mem) + let mem = aggregate_raw_ptr(p, ()); + opaque(&mem); +} diff --git a/tests/debuginfo/empty-string.rs b/tests/debuginfo/empty-string.rs index 36240730e19..35b68ed91c0 100644 --- a/tests/debuginfo/empty-string.rs +++ b/tests/debuginfo/empty-string.rs @@ -23,7 +23,7 @@ // lldb-check:[...] empty_string = "" { vec = size=0 } // lldb-command:fr v empty_str -// lldb-check:[...] empty_str = "" { data_ptr = [...] length = 0 } +// lldb-check:[...] empty_str = "" fn main() { let empty_string = String::new(); diff --git a/tests/debuginfo/pretty-slices.rs b/tests/debuginfo/pretty-slices.rs index 5d2086fa478..9defa344be0 100644 --- a/tests/debuginfo/pretty-slices.rs +++ b/tests/debuginfo/pretty-slices.rs @@ -27,10 +27,10 @@ // lldb-check:(&mut [i32]) mut_slice = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 } // lldb-command:v str_slice -// lldb-check:(&str) str_slice = "string slice" { data_ptr = [...] length = 12 } +// lldb-check:(&str) str_slice = "string slice" { [0] = 's' [1] = 't' [2] = 'r' [3] = 'i' [4] = 'n' [5] = 'g' [6] = ' ' [7] = 's' [8] = 'l' [9] = 'i' [10] = 'c' [11] = 'e' } // lldb-command:v mut_str_slice -// lldb-check:(&mut str) mut_str_slice = "mutable string slice" { data_ptr = [...] length = 20 } +// lldb-check:(&mut str) mut_str_slice = "mutable string slice" { [0] = 'm' [1] = 'u' [2] = 't' [3] = 'a' [4] = 'b' [5] = 'l' [6] = 'e' [7] = ' ' [8] = 's' [9] = 't' [10] = 'r' [11] = 'i' [12] = 'n' [13] = 'g' [14] = ' ' [15] = 's' [16] = 'l' [17] = 'i' [18] = 'c' [19] = 'e' } fn b() {} diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs new file mode 100644 index 00000000000..48d40d167ba --- /dev/null +++ b/tests/debuginfo/strings-and-strs.rs @@ -0,0 +1,63 @@ +//@ min-gdb-version: 14.0 +//@ min-lldb-version: 1800 + +//@ compile-flags:-g + +// === GDB TESTS =================================================================================== +// gdb-command:run + +// gdb-command:print plain_string +// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x55555555ab80}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}} + +// gdb-command:print plain_str +// gdbr-check:$2 = "Hello" + +// gdb-command:print str_in_struct +// gdbr-check:$3 = strings_and_strs::Foo {inner: "Hello"} + +// gdb-command:print str_in_tuple +// gdbr-check:$4 = ("Hello", "World") + +// gdb-command:print str_in_rc +// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcBox<&str>> {pointer: 0x55555555aae0}, phantom: core::marker::PhantomData<alloc::rc::RcBox<&str>>, alloc: alloc::alloc::Global} + + +// === LLDB TESTS ================================================================================== +// lldb-command:run +// lldb-command:v plain_string +// lldbg-check:(alloc::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } + +// lldb-command:v plain_str +// lldbg-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } + +// lldb-command:v str_in_struct +// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } + +// lldb-command:v str_in_tuple +// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } + +// lldb-command:v str_in_rc +// lldbg-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } + + +#![allow(unused_variables)] +#![feature(omit_gdb_pretty_printer_section)] +#![omit_gdb_pretty_printer_section] + +pub struct Foo<'a> { + inner: &'a str, +} + +fn main() { + let plain_string = String::from("Hello"); + let plain_str = "Hello"; + let str_in_struct = Foo { inner: "Hello" }; + let str_in_tuple = ("Hello", "World"); + + let str_in_rc = std::rc::Rc::new("Hello"); + zzz(); // #break +} + +fn zzz() { + () +} diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 68cb4d55e7b..25d0e5ccf49 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -69,9 +69,9 @@ + nop; StorageLive(_9); - _9 = _7; -- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); +- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); + _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -87,9 +87,9 @@ + nop; StorageLive(_13); - _13 = _7; -- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); +- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); + _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index fa184348b3b..3c5fd944d6b 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -69,9 +69,9 @@ + nop; StorageLive(_9); - _9 = _7; -- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); +- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe))); + _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -87,9 +87,9 @@ + nop; StorageLive(_13); - _13 = _7; -- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); +- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe))); + _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir index d7372a05082..a35af43cefd 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -105,7 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = {closure@main::{closure#0}}; Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_14); StorageLive(_15); StorageLive(_16); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 6ec62bfcf8c..2495719ec1c 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -105,7 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = {closure@main::{closure#0}}; Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Safe))); StorageDead(_14); StorageLive(_15); StorageLive(_16); diff --git a/tests/run-make/issue-28766/foo.rs b/tests/run-make/box-struct-no-segfault/foo.rs index 1dcabe42dc1..1dcabe42dc1 100644 --- a/tests/run-make/issue-28766/foo.rs +++ b/tests/run-make/box-struct-no-segfault/foo.rs diff --git a/tests/run-make/issue-28766/main.rs b/tests/run-make/box-struct-no-segfault/main.rs index de12b1fd9dc..de12b1fd9dc 100644 --- a/tests/run-make/issue-28766/main.rs +++ b/tests/run-make/box-struct-no-segfault/main.rs diff --git a/tests/run-make/box-struct-no-segfault/rmake.rs b/tests/run-make/box-struct-no-segfault/rmake.rs new file mode 100644 index 00000000000..5406f765e6c --- /dev/null +++ b/tests/run-make/box-struct-no-segfault/rmake.rs @@ -0,0 +1,13 @@ +// The crate "foo" tied to this test executes a very specific function, +// which involves boxing an instance of the struct Foo. However, +// this once caused a segmentation fault in cargo release builds due to an LLVM +// incorrect assertion. +// This test checks that this bug does not resurface. +// See https://github.com/rust-lang/rust/issues/28766 + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().opt().input("foo.rs").run(); + rustc().opt().library_search_path(tmp_dir()).input("main.rs").run(); +} diff --git a/tests/run-make/issue-28766/Makefile b/tests/run-make/issue-28766/Makefile deleted file mode 100644 index 96d0bdc2b2a..00000000000 --- a/tests/run-make/issue-28766/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) -O foo.rs - $(RUSTC) -O -L $(TMPDIR) main.rs diff --git a/tests/run-make/issue64319/Makefile b/tests/run-make/issue64319/Makefile deleted file mode 100644 index 56346cbcc15..00000000000 --- a/tests/run-make/issue64319/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Different optimization levels imply different values for `-Zshare-generics`, -# so try out a whole bunch of combinations to make sure everything is compatible -all: - # First up, try some defaults - $(RUSTC) --crate-type rlib foo.rs - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 - - # Next try mixing up some things explicitly - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - - # Now combine a whole bunch of options together - $(RUSTC) --crate-type rlib foo.rs - $(RUSTC) --crate-type dylib bar.rs - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no - $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes diff --git a/tests/run-make/rust-lld-by-default/main.rs b/tests/run-make/rust-lld-by-default/main.rs new file mode 100644 index 00000000000..e9f655fc09e --- /dev/null +++ b/tests/run-make/rust-lld-by-default/main.rs @@ -0,0 +1,5 @@ +// Test linking using `cc` with `rust-lld`, which is on by default on the x86_64-unknown-linux-gnu +// target. +// See https://github.com/rust-lang/compiler-team/issues/510 for more info + +fn main() {} diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs new file mode 100644 index 00000000000..876968727f3 --- /dev/null +++ b/tests/run-make/rust-lld-by-default/rmake.rs @@ -0,0 +1,43 @@ +// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu`, and that it can +// also be turned off with a CLI flag. + +//@ needs-rust-lld +//@ only-x86_64-unknown-linux-gnu + +extern crate run_make_support; + +use run_make_support::regex::Regex; +use run_make_support::rustc; +use std::process::Output; + +fn main() { + // A regular compilation should use rust-lld by default. We'll check that by asking the linker + // to display its version number with a link-arg. + let output = rustc() + .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") + .link_arg("-Wl,-v") + .input("main.rs") + .run(); + assert!( + find_lld_version_in_logs(output), + "the LLD version string should be present in the output logs" + ); + + // But it can still be disabled by turning the linker feature off. + let output = rustc() + .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") + .link_arg("-Wl,-v") + .arg("-Zlinker-features=-lld") + .input("main.rs") + .run(); + assert!( + !find_lld_version_in_logs(output), + "the LLD version string should not be present in the output logs" + ); +} + +fn find_lld_version_in_logs(output: Output) -> bool { + let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + stderr.lines().any(|line| lld_version_re.is_match(line)) +} diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile deleted file mode 100644 index 7786ff762cb..00000000000 --- a/tests/run-make/rustdoc-scrape-examples-invalid-expr/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -deps := ex - -include ../rustdoc-scrape-examples-multiple/scrape.mk - -all: scrape diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs new file mode 100644 index 00000000000..537d3e2d724 --- /dev/null +++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs @@ -0,0 +1,6 @@ +#[path = "../rustdoc-scrape-examples-remap/scrape.rs"] +mod scrape; + +fn main() { + scrape::scrape(); +} diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs index 1bc23ec8881..537d3e2d724 100644 --- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs @@ -1,49 +1,6 @@ -use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir}; -use std::fs::read_dir; -use std::path::Path; +#[path = "../rustdoc-scrape-examples-remap/scrape.rs"] +mod scrape; fn main() { - let lib_dir = tmp_dir(); - let out_dir = tmp_dir().join("rustdoc"); - let crate_name = "foobar"; - let deps = read_dir("examples") - .unwrap() - .filter_map(|entry| entry.ok().map(|e| e.path())) - .filter(|path| path.is_file() && path.extension().is_some_and(|ext| ext == "rs")) - .collect::<Vec<_>>(); - - rustc().input("src/lib.rs").crate_name(crate_name).crate_type("lib").emit("metadata").run(); - - let mut out_deps = Vec::with_capacity(deps.len()); - for dep in deps { - let dep_stem = dep.file_stem().unwrap(); - let out_example = out_dir.join(format!("{}.calls", dep_stem.to_str().unwrap())); - rustdoc() - .input(&dep) - .crate_name(&dep_stem) - .crate_type("bin") - .output(&out_dir) - .extern_(crate_name, lib_dir.join(format!("lib{crate_name}.rmeta"))) - .arg("-Zunstable-options") - .arg("--scrape-examples-output-path") - .arg(&out_example) - .arg("--scrape-examples-target-crate") - .arg(crate_name) - .run(); - out_deps.push(out_example); - } - - let mut rustdoc = rustdoc(); - rustdoc - .input("src/lib.rs") - .output(&out_dir) - .crate_name(crate_name) - .crate_type("lib") - .arg("-Zunstable-options"); - for dep in out_deps { - rustdoc.arg("--with-examples").arg(dep); - } - rustdoc.run(); - - assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success()); + scrape::scrape(); } diff --git a/tests/run-make/rustdoc-scrape-examples-remap/Makefile b/tests/run-make/rustdoc-scrape-examples-remap/Makefile deleted file mode 100644 index 7786ff762cb..00000000000 --- a/tests/run-make/rustdoc-scrape-examples-remap/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -deps := ex - -include ../rustdoc-scrape-examples-multiple/scrape.mk - -all: scrape diff --git a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs new file mode 100644 index 00000000000..d9deaf279ce --- /dev/null +++ b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs @@ -0,0 +1,5 @@ +mod scrape; + +fn main() { + scrape::scrape(); +} diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs new file mode 100644 index 00000000000..709388b5492 --- /dev/null +++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs @@ -0,0 +1,49 @@ +use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir}; +use std::fs::read_dir; +use std::path::Path; + +pub fn scrape() { + let lib_dir = tmp_dir(); + let out_dir = tmp_dir().join("rustdoc"); + let crate_name = "foobar"; + let deps = read_dir("examples") + .unwrap() + .filter_map(|entry| entry.ok().map(|e| e.path())) + .filter(|path| path.is_file() && path.extension().is_some_and(|ext| ext == "rs")) + .collect::<Vec<_>>(); + + rustc().input("src/lib.rs").crate_name(crate_name).crate_type("lib").emit("metadata").run(); + + let mut out_deps = Vec::with_capacity(deps.len()); + for dep in deps { + let dep_stem = dep.file_stem().unwrap(); + let out_example = out_dir.join(format!("{}.calls", dep_stem.to_str().unwrap())); + rustdoc() + .input(&dep) + .crate_name(&dep_stem) + .crate_type("bin") + .output(&out_dir) + .extern_(crate_name, lib_dir.join(format!("lib{crate_name}.rmeta"))) + .arg("-Zunstable-options") + .arg("--scrape-examples-output-path") + .arg(&out_example) + .arg("--scrape-examples-target-crate") + .arg(crate_name) + .run(); + out_deps.push(out_example); + } + + let mut rustdoc = rustdoc(); + rustdoc + .input("src/lib.rs") + .output(&out_dir) + .crate_name(crate_name) + .crate_type("lib") + .arg("-Zunstable-options"); + for dep in out_deps { + rustdoc.arg("--with-examples").arg(dep); + } + rustdoc.run(); + + assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success()); +} diff --git a/tests/run-make/issue64319/bar.rs b/tests/run-make/share-generics-export-again/bar.rs index 3895c0b6cdb..3895c0b6cdb 100644 --- a/tests/run-make/issue64319/bar.rs +++ b/tests/run-make/share-generics-export-again/bar.rs diff --git a/tests/run-make/issue64319/foo.rs b/tests/run-make/share-generics-export-again/foo.rs index c54a238e9ad..c54a238e9ad 100644 --- a/tests/run-make/issue64319/foo.rs +++ b/tests/run-make/share-generics-export-again/foo.rs diff --git a/tests/run-make/share-generics-export-again/rmake.rs b/tests/run-make/share-generics-export-again/rmake.rs new file mode 100644 index 00000000000..b9964eb442a --- /dev/null +++ b/tests/run-make/share-generics-export-again/rmake.rs @@ -0,0 +1,45 @@ +// When crates had different optimization levels, a bug caused +// incorrect symbol name generations. -Z share-generics could +// also fail to re-export upstream generics on multiple compile +// runs of the same dynamic library. + +// This test repeatedly compiles an rlib and a dylib with these flags +// to check if this bug ever returns. + +// See https://github.com/rust-lang/rust/pull/68277 +// See https://github.com/rust-lang/rust/issues/64319 +//@ ignore-cross-compile + +use run_make_support::rustc; + +fn main() { + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("3").run(); + rustc().crate_type("rlib").input("foo.rs").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=no").run(); + rustc().crate_type("rlib").input("foo.rs").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=yes").run(); + rustc().crate_type("rlib").input("foo.rs").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=no").run(); + rustc().crate_type("rlib").input("foo.rs").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=yes").run(); + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar.rs").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("1").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("1").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("1").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("2").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("2").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("2").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("3").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("3").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("3").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("s").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("s").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("s").arg("-Zshare-generics=yes").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("z").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("z").arg("-Zshare-generics=no").run(); + rustc().crate_type("dylib").input("bar.rs").opt_level("z").arg("-Zshare-generics=yes").run(); +} diff --git a/tests/run-make/static-unwinding/Makefile b/tests/run-make/static-unwinding/Makefile deleted file mode 100644 index 4b093f93608..00000000000 --- a/tests/run-make/static-unwinding/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: - $(RUSTC) lib.rs - $(RUSTC) main.rs - $(call RUN,main) diff --git a/tests/run-make/static-unwinding/rmake.rs b/tests/run-make/static-unwinding/rmake.rs new file mode 100644 index 00000000000..ee3d9a342f9 --- /dev/null +++ b/tests/run-make/static-unwinding/rmake.rs @@ -0,0 +1,15 @@ +// During unwinding, an implementation of Drop is possible to clean up resources. +// This test implements drop in both a main function and its static library. +// If the test succeeds, a Rust program being a static library does not affect Drop implementations. +// See https://github.com/rust-lang/rust/issues/10434 + +//@ ignore-cross-compile +//@ needs-unwind + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("lib.rs").run(); + rustc().input("main.rs").run(); + run("main"); +} diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs new file mode 100644 index 00000000000..584a610ed63 --- /dev/null +++ b/tests/run-make/stdin-rustdoc/rmake.rs @@ -0,0 +1,25 @@ +//! This test checks rustdoc `-` (stdin) handling + +use run_make_support::{rustdoc, tmp_dir}; + +static INPUT: &str = r#" +//! ``` +//! dbg!(()); +//! ``` +pub struct F; +"#; + +fn main() { + let tmp_dir = tmp_dir(); + let out_dir = tmp_dir.join("doc"); + + // rustdoc - + rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run(); + assert!(out_dir.join("rust_out/struct.F.html").try_exists().unwrap()); + + // rustdoc --test - + rustdoc().arg("--test").arg("-").stdin(INPUT).run(); + + // rustdoc file.rs - + rustdoc().arg("file.rs").arg("-").run_fail(); +} diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr index 77fbaf52934..bf53089675d 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr @@ -1,8 +1,11 @@ -error: the type `Foo::Bar<Vec<[u32]>>` is not well-formed - --> $DIR/wf-check-skipped.rs:17:14 +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/wf-check-skipped.rs:17:25 | LL | fn main() -> Foo::Bar::<Vec<[u32]>> {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs index 5b812a2295e..52df4efd13e 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs @@ -15,4 +15,4 @@ impl Foo { } fn main() -> Foo::Bar::<Vec<[u32]>> {} -//[next]~^ ERROR the type `Foo::Bar<Vec<[u32]>>` is not well-formed +//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time diff --git a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs index f213e8933bf..85c08ec035e 100644 --- a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs +++ b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs @@ -1,4 +1,15 @@ const X: i32 = #[allow(dead_code)] 8; //~^ ERROR attributes on expressions are experimental +const Y: i32 = + /// foo +//~^ ERROR attributes on expressions are experimental + 8; + +const Z: i32 = { + //! foo +//~^ ERROR attributes on expressions are experimental + 8 +}; + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr index 67fdae030c0..14f7d58e47a 100644 --- a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr +++ b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr @@ -8,6 +8,28 @@ LL | const X: i32 = #[allow(dead_code)] 8; = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: attributes on expressions are experimental + --> $DIR/feature-gate-stmt_expr_attributes.rs:5:5 + | +LL | /// foo + | ^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: `///` is used for outer documentation comments; for a plain comment, use `//` + +error[E0658]: attributes on expressions are experimental + --> $DIR/feature-gate-stmt_expr_attributes.rs:10:5 + | +LL | //! foo + | ^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 6855e17df9a..98609211865 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -11,31 +11,13 @@ help: consider mutably borrowing here LL | for item in &mut *things { *item = 0 } | ++++ -error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed - --> $DIR/issue-20605.rs:6:17 - | -LL | for item in *things { *item = 0 } - | ^^^^^^^ - -error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed - --> $DIR/issue-20605.rs:6:17 - | -LL | for item in *things { *item = 0 } - | ^^^^^^^ - -error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed - --> $DIR/issue-20605.rs:6:17 - | -LL | for item in *things { *item = 0 } - | ^^^^^^^ - error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced --> $DIR/issue-20605.rs:6:27 | LL | for item in *things { *item = 0 } | ^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0614. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index b923a7088fe..647dc84028c 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -6,9 +6,6 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) { for item in *things { *item = 0 } //[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator //[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator - //[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed - //[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed - //[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed //[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced // FIXME(-Znext-solver): these error messages are horrible and have to be diff --git a/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs new file mode 100644 index 00000000000..96a0f2f40bf --- /dev/null +++ b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs @@ -0,0 +1,19 @@ +// Fix for <https://github.com/rust-lang/rust/issues/125196>. +//@ check-pass + +trait Tr { + type Gat<T>; +} + +struct W<T>(T); + +fn foo<T: Tr>() where for<'a> &'a T: Tr<Gat<W<i32>> = i32> { + let x: <&T as Tr>::Gat<W<_>> = 1i32; + // Previously, `match_projection_projections` only checked that + // `shallow_resolve(W<?0>) = W<?0>`. This won't prevent *all* inference guidance + // from projection predicates in the environment, just ones that guide the + // outermost type of each GAT constructor. This is definitely wrong, but there is + // code that relies on it in the wild :/ +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs index 365955166e6..5a6bf9bfaef 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs @@ -14,6 +14,6 @@ struct W<T>(T); // `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still // encounter weak types in `assemble_alias_bound_candidates_recur`. fn hello(_: W<A<usize>>) {} -//~^ ERROR the type `W<A<usize>>` is not well-formed +//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time fn main() {} diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 5df27ac3bc6..9663fab3d8c 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -7,11 +7,14 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information = note: `#[warn(incomplete_features)]` on by default -error: the type `W<A<usize>>` is not well-formed +error[E0277]: the size for values of type `A<usize>` cannot be known at compilation time --> $DIR/alias-bounds-when-not-wf.rs:16:13 | LL | fn hello(_: W<A<usize>>) {} - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `A<usize>` error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index 2e0812d6472..d73d5bab8d7 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -22,7 +22,7 @@ error[E0308]: intrinsic has wrong type --> $DIR/safe-intrinsic-mismatch.rs:11:16 | LL | const fn assume(_b: bool) {} - | ^ expected unsafe fn, found normal fn + | ^ expected unsafe fn, found safe fn | = note: expected signature `unsafe fn(_)` found signature `fn(_)` @@ -37,7 +37,7 @@ error[E0308]: intrinsic has wrong type --> $DIR/safe-intrinsic-mismatch.rs:15:26 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - | ^ expected unsafe fn, found normal fn + | ^ expected unsafe fn, found safe fn | = note: expected signature `unsafe fn(_, _, _)` found signature `fn(_, _, _)` diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr index add85b2f5e0..1ff5c8d8825 100644 --- a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr +++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -13,7 +13,7 @@ LL | (/// useless doc comment = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: `///` is for documentation comments. For a plain comment, use `//`. + = help: `///` is used for outer documentation comments; for a plain comment, use `//` error: unused doc comment --> $DIR/unused-doc-comments-edge-cases.rs:6:9 diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.rs b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs index 4d51db89bc0..0c8fe65bd5c 100644 --- a/tests/ui/lint/unused/unused-macro-rules-compile-error.rs +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs @@ -9,7 +9,7 @@ macro_rules! num { // Some nested use (two_) => { foo(compile_error!("foo")); }; (three) => { 3 }; - (four) => { 4 }; //~ ERROR: rule of macro + (four) => { 4 }; //~ ERROR: rule #5 of macro } const _NUM: u8 = num!(one) + num!(three); @@ -17,9 +17,9 @@ const _NUM: u8 = num!(one) + num!(three); macro_rules! num2 { (one) => { 1 }; // Only identifier present - (two) => { fn compile_error() {} }; //~ ERROR: rule of macro + (two) => { fn compile_error() {} }; //~ ERROR: rule #2 of macro // Only identifier and bang present - (two_) => { compile_error! }; //~ ERROR: rule of macro + (two_) => { compile_error! }; //~ ERROR: rule #3 of macro (three) => { 3 }; } const _NUM2: u8 = num2!(one) + num2!(three); diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr index 76af8c967db..936428f6a1c 100644 --- a/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr @@ -1,4 +1,4 @@ -error: 5th rule of macro `num` is never used +error: rule #5 of macro `num` is never used --> $DIR/unused-macro-rules-compile-error.rs:12:5 | LL | (four) => { 4 }; @@ -10,13 +10,13 @@ note: the lint level is defined here LL | #![deny(unused_macro_rules)] | ^^^^^^^^^^^^^^^^^^ -error: 3rd rule of macro `num2` is never used +error: rule #3 of macro `num2` is never used --> $DIR/unused-macro-rules-compile-error.rs:22:5 | LL | (two_) => { compile_error! }; | ^^^^^^ -error: 2nd rule of macro `num2` is never used +error: rule #2 of macro `num2` is never used --> $DIR/unused-macro-rules-compile-error.rs:20:5 | LL | (two) => { fn compile_error() {} }; diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.rs b/tests/ui/lint/unused/unused-macro-rules-decl.rs index 537c84940fd..ca14d58e524 100644 --- a/tests/ui/lint/unused/unused-macro-rules-decl.rs +++ b/tests/ui/lint/unused/unused-macro-rules-decl.rs @@ -6,9 +6,9 @@ // Most simple case macro num { (one) => { 1 }, - (two) => { 2 }, //~ ERROR: 2nd rule of macro + (two) => { 2 }, //~ ERROR: rule #2 of macro (three) => { 3 }, - (four) => { 4 }, //~ ERROR: 4th rule of macro + (four) => { 4 }, //~ ERROR: rule #4 of macro } const _NUM: u8 = num!(one) + num!(three); @@ -28,7 +28,7 @@ macro num_rec { (two) => { num_rec!(one) + num_rec!(one) }, - (three) => { //~ ERROR: 3rd rule of macro + (three) => { //~ ERROR: rule #3 of macro num_rec!(one) + num_rec!(two) }, (four) => { diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.stderr b/tests/ui/lint/unused/unused-macro-rules-decl.stderr index 4d9b22feda2..10ceb3921f3 100644 --- a/tests/ui/lint/unused/unused-macro-rules-decl.stderr +++ b/tests/ui/lint/unused/unused-macro-rules-decl.stderr @@ -1,4 +1,4 @@ -error: 4th rule of macro `num` is never used +error: rule #4 of macro `num` is never used --> $DIR/unused-macro-rules-decl.rs:11:5 | LL | (four) => { 4 }, @@ -10,13 +10,13 @@ note: the lint level is defined here LL | #![deny(unused_macro_rules)] | ^^^^^^^^^^^^^^^^^^ -error: 2nd rule of macro `num` is never used +error: rule #2 of macro `num` is never used --> $DIR/unused-macro-rules-decl.rs:9:5 | LL | (two) => { 2 }, | ^^^^^ -error: 3rd rule of macro `num_rec` is never used +error: rule #3 of macro `num_rec` is never used --> $DIR/unused-macro-rules-decl.rs:31:5 | LL | (three) => { diff --git a/tests/ui/lint/unused/unused-macro-rules.rs b/tests/ui/lint/unused/unused-macro-rules.rs index eeaf4d1b0a9..39a882e8e4d 100644 --- a/tests/ui/lint/unused/unused-macro-rules.rs +++ b/tests/ui/lint/unused/unused-macro-rules.rs @@ -5,9 +5,9 @@ // Most simple case macro_rules! num { (one) => { 1 }; - (two) => { 2 }; //~ ERROR: 2nd rule of macro + (two) => { 2 }; //~ ERROR: rule #2 of macro (three) => { 3 }; - (four) => { 4 }; //~ ERROR: 4th rule of macro + (four) => { 4 }; //~ ERROR: rule #4 of macro } const _NUM: u8 = num!(one) + num!(three); @@ -27,7 +27,7 @@ macro_rules! num_rec { (two) => { num_rec!(one) + num_rec!(one) }; - (three) => { //~ ERROR: 3rd rule of macro + (three) => { //~ ERROR: rule #3 of macro num_rec!(one) + num_rec!(two) }; (four) => { num_rec!(two) + num_rec!(two) }; diff --git a/tests/ui/lint/unused/unused-macro-rules.stderr b/tests/ui/lint/unused/unused-macro-rules.stderr index 2b3098a5128..b9258e77805 100644 --- a/tests/ui/lint/unused/unused-macro-rules.stderr +++ b/tests/ui/lint/unused/unused-macro-rules.stderr @@ -1,4 +1,4 @@ -error: 4th rule of macro `num` is never used +error: rule #4 of macro `num` is never used --> $DIR/unused-macro-rules.rs:10:5 | LL | (four) => { 4 }; @@ -10,13 +10,13 @@ note: the lint level is defined here LL | #![deny(unused_macro_rules)] | ^^^^^^^^^^^^^^^^^^ -error: 2nd rule of macro `num` is never used +error: rule #2 of macro `num` is never used --> $DIR/unused-macro-rules.rs:8:5 | LL | (two) => { 2 }; | ^^^^^ -error: 3rd rule of macro `num_rec` is never used +error: rule #3 of macro `num_rec` is never used --> $DIR/unused-macro-rules.rs:30:5 | LL | (three) => { diff --git a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr new file mode 100644 index 00000000000..5e880964454 --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr @@ -0,0 +1,32 @@ +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:21:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2021_inline_const.rs:10:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:22:12 + | +LL | macro_rules! m2024 { + | ------------------ when calling this macro +... +LL | m2024!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/expr_2021_inline_const.rs:16:6 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr new file mode 100644 index 00000000000..237ecb2cc19 --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr @@ -0,0 +1,17 @@ +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:21:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2021_inline_const.rs:10:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/expr_2021_inline_const.rs b/tests/ui/macros/expr_2021_inline_const.rs new file mode 100644 index 00000000000..ebc5ea36421 --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.rs @@ -0,0 +1,23 @@ +//@ revisions: edi2021 edi2024 +//@[edi2024]compile-flags: --edition=2024 -Z unstable-options +//@[edi2021]compile-flags: --edition=2021 + +// This test ensures that the inline const match only on edition 2024 +#![feature(expr_fragment_specifier_2024)] +#![allow(incomplete_features)] + +macro_rules! m2021 { + ($e:expr_2021) => { + $e + }; +} + +macro_rules! m2024 { + ($e:expr) => { + $e + }; +} +fn main() { + m2021!(const { 1 }); //~ ERROR: no rules expected the token `const` + m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected the token `const` +} diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs new file mode 100644 index 00000000000..a7711266106 --- /dev/null +++ b/tests/ui/macros/expr_2021_old_edition.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --edition=2018 + +// This test ensures that expr_2021 is not allowed on pre-2021 editions + +macro_rules! m { + ($e:expr_2021) => { //~ ERROR: invalid fragment specifier `expr_2021` + $e + }; +} + +fn main() { + m!(()); //~ ERROR: no rules expected the token `(` +} diff --git a/tests/ui/macros/expr_2021_old_edition.stderr b/tests/ui/macros/expr_2021_old_edition.stderr new file mode 100644 index 00000000000..bffa8a1ca17 --- /dev/null +++ b/tests/ui/macros/expr_2021_old_edition.stderr @@ -0,0 +1,26 @@ +error: invalid fragment specifier `expr_2021` + --> $DIR/expr_2021_old_edition.rs:6:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + | + = help: fragment specifier `expr_2021` requires Rust 2021 or later + valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: no rules expected the token `(` + --> $DIR/expr_2021_old_edition.rs:12:8 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(()); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:ident` + --> $DIR/expr_2021_old_edition.rs:6:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs new file mode 100644 index 00000000000..5a737b29821 --- /dev/null +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --edition=2024 -Z unstable-options + +macro_rules! m { + ($e:expr_2021) => { //~ ERROR: fragment specifier `expr_2021` is unstable + $e + }; +} + +fn main() { + m!(()); +} diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr new file mode 100644 index 00000000000..273a93877ce --- /dev/null +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr @@ -0,0 +1,13 @@ +error[E0658]: fragment specifier `expr_2021` is unstable + --> $DIR/feature-gate-expr_fragment_specifier_2024.rs:4:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + | + = note: see issue #123742 <https://github.com/rust-lang/rust/issues/123742> for more information + = help: add `#![feature(expr_fragment_specifier_2024)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/issue-98790.rs b/tests/ui/macros/issue-98790.rs deleted file mode 100644 index b489efe9ce9..00000000000 --- a/tests/ui/macros/issue-98790.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass - -macro_rules! stringify_item { - ($item:item) => { - stringify!($item) - }; -} - -macro_rules! repro { - ($expr:expr) => { - stringify_item! { - pub fn repro() -> bool { - $expr - } - } - }; -} - -fn main() { - assert_eq!( - repro!(match () { () => true } | true), - "pub fn repro() -> bool { (match () { () => true, }) | true }" - ); -} diff --git a/tests/ui/macros/missing-semi.rs b/tests/ui/macros/missing-semi.rs new file mode 100644 index 00000000000..b7e90e9e442 --- /dev/null +++ b/tests/ui/macros/missing-semi.rs @@ -0,0 +1,11 @@ +#[allow(unused_macros)] +macro_rules! foo { + () => { + + } + () => { + //~^ ERROR expected `;`, found `(` + } +} + +fn main() {} diff --git a/tests/ui/macros/missing-semi.stderr b/tests/ui/macros/missing-semi.stderr new file mode 100644 index 00000000000..0a7afe50059 --- /dev/null +++ b/tests/ui/macros/missing-semi.stderr @@ -0,0 +1,8 @@ +error: expected `;`, found `(` + --> $DIR/missing-semi.rs:6:5 + | +LL | () => { + | ^ no rules expected this token in macro call + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/println-percent-prefix-num-issue-125002.rs b/tests/ui/macros/println-percent-prefix-num-issue-125002.rs new file mode 100644 index 00000000000..9f30d48a5cd --- /dev/null +++ b/tests/ui/macros/println-percent-prefix-num-issue-125002.rs @@ -0,0 +1,6 @@ +fn main() { + println!("%100000", 1); + //~^ ERROR argument never used + println!("% 65536", 1); + //~^ ERROR argument never used +} diff --git a/tests/ui/macros/println-percent-prefix-num-issue-125002.stderr b/tests/ui/macros/println-percent-prefix-num-issue-125002.stderr new file mode 100644 index 00000000000..7575137be6d --- /dev/null +++ b/tests/ui/macros/println-percent-prefix-num-issue-125002.stderr @@ -0,0 +1,28 @@ +error: argument never used + --> $DIR/println-percent-prefix-num-issue-125002.rs:2:25 + | +LL | println!("%100000", 1); + | ^ argument never used + | +note: format specifiers use curly braces, and the conversion specifier `1` is unknown or unsupported + --> $DIR/println-percent-prefix-num-issue-125002.rs:2:15 + | +LL | println!("%100000", 1); + | ^^ + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: argument never used + --> $DIR/println-percent-prefix-num-issue-125002.rs:4:29 + | +LL | println!("% 65536", 1); + | ^ argument never used + | +note: format specifiers use curly braces, and the conversion specifier ` ` is unknown or unsupported + --> $DIR/println-percent-prefix-num-issue-125002.rs:4:15 + | +LL | println!("% 65536", 1); + | ^^ + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/signature.stderr b/tests/ui/proc-macro/signature.stderr index 2a53145a643..fd679442b6a 100644 --- a/tests/ui/proc-macro/signature.stderr +++ b/tests/ui/proc-macro/signature.stderr @@ -2,7 +2,7 @@ error: derive proc macro has incorrect signature --> $DIR/signature.rs:10:1 | LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` found signature `unsafe extern "C" fn(i32, u32) -> u32` diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr index 2061fc78575..77d542c729a 100644 --- a/tests/ui/traits/impl-method-mismatch.stderr +++ b/tests/ui/traits/impl-method-mismatch.stderr @@ -2,7 +2,7 @@ error[E0053]: method `jumbo` has an incompatible type for trait --> $DIR/impl-method-mismatch.rs:7:5 | LL | unsafe fn jumbo(&self, x: &usize) { *self + *x; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn | note: type in trait --> $DIR/impl-method-mismatch.rs:2:5 diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 044c24fd2b2..170f2c7d34c 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0282]: type annotations needed +error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X<const FN: fn() = { || {} }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{ || {} }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 @@ -23,4 +23,4 @@ LL | struct X<const FN: fn() = { || {} }>; error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index 6e68646fbe4..57cba790b55 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,12 +1,12 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>` +error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl<T: ?Sized + TwoW> Trait for W<T> {} | ------------------------------------- first implementation here LL | impl<T: ?Sized + TwoW> Trait for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` | - = note: overflow evaluating the requirement `W<W<W<W<_>>>>: TwoW` + = note: overflow evaluating the requirement `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>: TwoW` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index df25150c21f..8d7d8cee08a 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `_: Sized` +error[E0275]: overflow evaluating the requirement `W<_>: Trait` --> $DIR/fixpoint-exponential-growth.rs:33:13 | LL | impls::<W<_>>(); | ^^^^ | -note: required for `W<(W<_>, W<_>)>` to implement `Trait` - --> $DIR/fixpoint-exponential-growth.rs:23:12 - | -LL | impl<T, U> Trait for W<(W<T>, W<U>)> - | - ^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/fixpoint-exponential-growth.rs:30:13 | diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr index 86c71ad92ff..7cedb4d36c9 100644 --- a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr +++ b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr @@ -1,53 +1,21 @@ -error[E0275]: overflow evaluating the requirement `(): Inductive` +error[E0275]: overflow evaluating the requirement `(): Trait` --> $DIR/double-cycle-inductive-coinductive.rs:32:19 | LL | impls_trait::<()>(); | ^^ | -note: required for `()` to implement `Trait` - --> $DIR/double-cycle-inductive-coinductive.rs:9:34 - | -LL | impl<T: Inductive + Coinductive> Trait for T {} - | --------- ^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `Inductive` - --> $DIR/double-cycle-inductive-coinductive.rs:12:16 - | -LL | impl<T: Trait> Inductive for T {} - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 7 redundant requirements hidden - = note: required for `()` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/double-cycle-inductive-coinductive.rs:17:19 | LL | fn impls_trait<T: Trait>() {} | ^^^^^ required by this bound in `impls_trait` -error[E0275]: overflow evaluating the requirement `(): CoinductiveRev` +error[E0275]: overflow evaluating the requirement `(): TraitRev` --> $DIR/double-cycle-inductive-coinductive.rs:35:23 | LL | impls_trait_rev::<()>(); | ^^ | -note: required for `()` to implement `TraitRev` - --> $DIR/double-cycle-inductive-coinductive.rs:21:40 - | -LL | impl<T: CoinductiveRev + InductiveRev> TraitRev for T {} - | -------------- ^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `CoinductiveRev` - --> $DIR/double-cycle-inductive-coinductive.rs:27:19 - | -LL | impl<T: TraitRev> CoinductiveRev for T {} - | -------- ^^^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 7 redundant requirements hidden - = note: required for `()` to implement `TraitRev` note: required by a bound in `impls_trait_rev` --> $DIR/double-cycle-inductive-coinductive.rs:29:23 | diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr index ea46c0fea97..a2a5c028cf8 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr @@ -1,19 +1,9 @@ -error[E0275]: overflow evaluating the requirement `W<W<_>>: Trait` +error[E0275]: overflow evaluating the requirement `W<_>: Trait` --> $DIR/inductive-fixpoint-hang.rs:31:19 | LL | impls_trait::<W<_>>(); | ^^^^ | -note: required for `W<W<W<_>>>` to implement `Trait` - --> $DIR/inductive-fixpoint-hang.rs:22:17 - | -LL | impl<T: ?Sized> Trait for W<W<T>> - | ^^^^^ ^^^^^^^ -LL | where -LL | W<T>: Trait, - | ----- unsatisfied trait bound introduced here - = note: 8 redundant requirements hidden - = note: required for `W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/inductive-fixpoint-hang.rs:28:19 | diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs index 9d0ea51b1b2..78683372580 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs @@ -39,7 +39,7 @@ fn impls_ar<T: AR>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): B` + //~^ ERROR overflow evaluating the requirement `(): A` impls_ar::<()>(); //~^ ERROR overflow evaluating the requirement `(): AR` diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr index fe02d3c407c..e9cc6bc6c81 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr @@ -1,25 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): B` +error[E0275]: overflow evaluating the requirement `(): A` --> $DIR/inductive-not-on-stack.rs:41:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `A` - --> $DIR/inductive-not-on-stack.rs:21:16 - | -LL | impl<T: B + C> A for T {} - | - ^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `B` - --> $DIR/inductive-not-on-stack.rs:22:12 - | -LL | impl<T: A> B for T {} - | - ^ ^ - | | - | unsatisfied trait bound introduced here - = note: 7 redundant requirements hidden - = note: required for `()` to implement `A` note: required by a bound in `impls_a` --> $DIR/inductive-not-on-stack.rs:25:15 | @@ -32,29 +16,6 @@ error[E0275]: overflow evaluating the requirement `(): AR` LL | impls_ar::<()>(); | ^^ | -note: required for `()` to implement `BR` - --> $DIR/inductive-not-on-stack.rs:35:13 - | -LL | impl<T: AR> BR for T {} - | -- ^^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `CR` - --> $DIR/inductive-not-on-stack.rs:36:13 - | -LL | impl<T: BR> CR for T {} - | -- ^^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `AR` - --> $DIR/inductive-not-on-stack.rs:34:18 - | -LL | impl<T: CR + BR> AR for T {} - | -- ^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 6 redundant requirements hidden - = note: required for `()` to implement `AR` note: required by a bound in `impls_ar` --> $DIR/inductive-not-on-stack.rs:38:16 | diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs index b90a354be1b..6d75d241864 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs @@ -35,5 +35,5 @@ fn impls_a<T: A>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): CInd` + //~^ ERROR overflow evaluating the requirement `(): A` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr index 03e61dbf99c..17544eb1da5 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr @@ -1,46 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): CInd` +error[E0275]: overflow evaluating the requirement `(): A` --> $DIR/mixed-cycles-1.rs:37:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `B` - --> $DIR/mixed-cycles-1.rs:31:28 - | -LL | impl<T: ?Sized + CInd + C> B for T {} - | ---- ^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `C` - --> $DIR/mixed-cycles-1.rs:32:25 - | -LL | impl<T: ?Sized + B + A> C for T {} - | - ^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `CInd` - --> $DIR/mixed-cycles-1.rs:28:21 - | -LL | impl<T: ?Sized + C> CInd for T {} - | - ^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 4 redundant requirements hidden - = note: required for `()` to implement `B` -note: required for `()` to implement `BInd` - --> $DIR/mixed-cycles-1.rs:23:21 - | -LL | impl<T: ?Sized + B> BInd for T {} - | - ^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `A` - --> $DIR/mixed-cycles-1.rs:30:28 - | -LL | impl<T: ?Sized + BInd + C> A for T {} - | ---- ^ ^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-1.rs:34:15 | diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs index a3ffcaafb37..c939a6e5ef2 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs @@ -28,5 +28,5 @@ fn impls_a<T: A>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): BInd` + //~^ ERROR overflow evaluating the requirement `(): A` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr index 892426abe82..a9be1016c74 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr @@ -1,32 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): BInd` +error[E0275]: overflow evaluating the requirement `(): A` --> $DIR/mixed-cycles-2.rs:30:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `B` - --> $DIR/mixed-cycles-2.rs:25:24 - | -LL | impl<T: ?Sized + BInd> B for T {} - | ---- ^ ^ - | | - | unsatisfied trait bound introduced here -note: required for `()` to implement `BInd` - --> $DIR/mixed-cycles-2.rs:22:21 - | -LL | impl<T: ?Sized + B> BInd for T {} - | - ^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 6 redundant requirements hidden - = note: required for `()` to implement `BInd` -note: required for `()` to implement `A` - --> $DIR/mixed-cycles-2.rs:24:28 - | -LL | impl<T: ?Sized + BInd + B> A for T {} - | ---- ^ ^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-2.rs:27:15 | diff --git a/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.rs b/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.rs new file mode 100644 index 00000000000..4094ab84166 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver + +trait Trait { + type Assoc; +} + +struct W<T>(*mut T); +impl<T> Trait for W<W<T>> +where + W<T>: Trait, +{ + type Assoc = (); +} + +trait NoOverlap {} +impl<T: Trait> NoOverlap for T {} + +impl<T: Trait<Assoc = u32>> NoOverlap for W<T> {} +//~^ ERROR conflicting implementations of trait `NoOverlap` for type `W<_>` + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.stderr b/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.stderr new file mode 100644 index 00000000000..42be1960563 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/ambiguous-fail.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `NoOverlap` for type `W<_>` + --> $DIR/ambiguous-fail.rs:18:1 + | +LL | impl<T: Trait> NoOverlap for T {} + | ------------------------------ first implementation here +LL | +LL | impl<T: Trait<Assoc = u32>> NoOverlap for W<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.rs b/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.rs new file mode 100644 index 00000000000..2d40ba37a89 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver + +trait Trait { + type Assoc; +} + +struct W<T>(*mut T); +impl<T> Trait for W<W<T>> +where + W<T>: Trait, +{ + type Assoc = (); +} + +trait NoOverlap {} +impl<T: Trait> NoOverlap for T {} + +impl<T: Trait<Assoc = ()>> NoOverlap for W<T> {} +//~^ ERROR conflicting implementations of trait `NoOverlap` for type `W<_>` + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.stderr b/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.stderr new file mode 100644 index 00000000000..5c77fc71e55 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/ambiguous-pass.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `NoOverlap` for type `W<_>` + --> $DIR/ambiguous-pass.rs:18:1 + | +LL | impl<T: Trait> NoOverlap for T {} + | ------------------------------ first implementation here +LL | +LL | impl<T: Trait<Assoc = ()>> NoOverlap for W<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 8667b3fe466..9f6dea5d5bf 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -12,7 +12,7 @@ trait ToUnit<'a> { trait Overlap<T> {} type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; -//~^ ERROR: not well-formed +//~^ ERROR the trait bound `*const T: ToUnit<'a>` is not satisfied impl<T> Overlap<T> for T {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 5cb24fa19aa..2e0566cad08 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -13,11 +13,17 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information = note: `#[warn(incomplete_features)]` on by default -error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed +error[E0277]: the trait bound `*const T: ToUnit<'a>` is not satisfied --> $DIR/issue-118950-root-region.rs:14:21 | LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToUnit<'a>` is not implemented for `*const T` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-118950-root-region.rs:8:1 + | +LL | trait ToUnit<'a> { + | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(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::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } @@ -34,5 +40,5 @@ LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> { error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0119, E0412. +Some errors have detailed explanations: E0119, E0277, E0412. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs deleted file mode 100644 index a5696fc7796..00000000000 --- a/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ compile-flags: -Znext-solver - -trait Trait { - type Ty; -} - -impl Trait for for<'a> fn(&'a u8, &'a u8) { - type Ty = (); -} - -// argument is necessary to create universes before registering the hidden type. -fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized { - //~^ ERROR the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed - "hidden type is `&'?0 str` with '?0 member of ['static,]" -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr b/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr deleted file mode 100644 index 7a9982f07f6..00000000000 --- a/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed - --> $DIR/member-constraints-in-root-universe.rs:12:16 - | -LL | fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs index 3aa1af4956e..a347984daf6 100644 --- a/tests/ui/traits/next-solver/object-unsafety.rs +++ b/tests/ui/traits/next-solver/object-unsafety.rs @@ -10,9 +10,8 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { pub fn copy_any<T>(t: &T) -> T { copy::<dyn Setup<From=T>>(t) - //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed + //~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>` //~| ERROR mismatched types - //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed //~| ERROR the trait bound `T: Copy` is not satisfied // FIXME(-Znext-solver): These error messages are horrible and some of them diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index 7c9a6077fe7..75d0ce24413 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -15,12 +15,6 @@ help: consider restricting type parameter `T` LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { | +++++++++++++++++++ -error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed - --> $DIR/object-unsafety.rs:12:31 - | -LL | copy::<dyn Setup<From=T>>(t) - | ^ - error[E0308]: mismatched types --> $DIR/object-unsafety.rs:12:31 | @@ -37,13 +31,19 @@ note: function defined here LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { | ^^^^ -------------- -error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed +error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>` --> $DIR/object-unsafety.rs:12:5 | LL | copy::<dyn Setup<From=T>>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup` + | + = note: required because it appears within the type `dyn Setup<From = T>` +help: consider restricting type parameter `T` + | +LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { + | +++++++++++++++++++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs index 052d803765d..186d0e8be56 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs @@ -15,5 +15,5 @@ fn impls<T: Trait>() {} fn main() { impls::<W<_>>(); - //~^ ERROR overflow evaluating the requirement `_: Sized` + //~^ ERROR overflow evaluating the requirement `W<_>: Trait` } diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr index 6583cae8bb9..b032ae3e740 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `_: Sized` +error[E0275]: overflow evaluating the requirement `W<_>: Trait` --> $DIR/exponential-trait-goals.rs:17:13 | LL | impls::<W<_>>(); | ^^^^ | -note: required for `W<(W<_>, W<_>)>` to implement `Trait` - --> $DIR/exponential-trait-goals.rs:7:12 - | -LL | impl<T, U> Trait for W<(W<T>, W<U>)> - | - ^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/exponential-trait-goals.rs:14:13 | diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr index 9e467721e83..67616619384 100644 --- a/tests/ui/traits/next-solver/overflow/global-cache.stderr +++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr @@ -5,15 +5,6 @@ LL | impls_trait::<Four<Four<Four<Four<()>>>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`) -note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>` to implement `Trait` - --> $DIR/global-cache.rs:12:16 - | -LL | impl<T: Trait> Trait for Inc<T> {} - | ----- ^^^^^ ^^^^^^ - | | - | unsatisfied trait bound introduced here - = note: 5 redundant requirements hidden - = note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/global-cache.rs:15:19 | diff --git a/tests/ui/unpretty/auxiliary/data.txt b/tests/ui/unpretty/auxiliary/data.txt new file mode 100644 index 00000000000..2f62e4609f4 --- /dev/null +++ b/tests/ui/unpretty/auxiliary/data.txt @@ -0,0 +1 @@ +data for include_bytes in ../expanded-exhaustive.rs diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs new file mode 100644 index 00000000000..6aa032d7ed8 --- /dev/null +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -0,0 +1,888 @@ +//@ compile-flags: -Zunpretty=expanded -Zunstable-options +//@ edition:2024 +//@ check-pass + +#![feature(async_closure)] +#![feature(auto_traits)] +#![feature(box_patterns)] +#![feature(builtin_syntax)] +#![feature(concat_idents)] +#![feature(const_trait_impl)] +#![feature(core_pattern_type)] +#![feature(decl_macro)] +#![feature(deref_patterns)] +#![feature(explicit_tail_calls)] +#![feature(gen_blocks)] +#![feature(let_chains)] +#![feature(more_qualified_paths)] +#![feature(never_patterns)] +#![feature(never_type)] +#![feature(pattern_types)] +#![feature(prelude_import)] +#![feature(raw_ref_op)] +#![feature(specialization)] +#![feature(trace_macros)] +#![feature(trait_alias)] +#![feature(try_blocks)] +#![feature(unnamed_fields)] +#![feature(yeet_expr)] +#![allow(incomplete_features)] + +#[prelude_import] +use self::prelude::*; + +mod prelude { + pub use std::prelude::rust_2024::*; + + pub type T = _; + + pub trait Trait { + const CONST: (); + } +} + +mod attributes { + //! inner single-line doc comment + /*! + * inner multi-line doc comment + */ + #![doc = "inner doc attribute"] + #![allow(dead_code, unused_variables)] + #![no_std] + + /// outer single-line doc comment + /** + * outer multi-line doc comment + */ + #[doc = "outer doc attribute"] + #[doc = concat!("mac", "ro")] + #[allow()] + #[repr(C)] + struct Struct; +} + +mod expressions { + /// ExprKind::Array + fn expr_array() { + []; + [true]; + [true,]; + [true, true]; + ["long........................................................................"]; + ["long............................................................", true]; + } + + /// ExprKind::ConstBlock + fn expr_const_block() { + const {}; + const { 1 }; + const { struct S; }; + } + + /// ExprKind::Call + fn expr_call() { + let f; + f(); + f::<u8>(); + f::<1>(); + f::<'static, u8, 1>(); + f(true); + f(true,); + ()(); + } + + /// ExprKind::MethodCall + fn expr_method_call() { + let x; + x.f(); + x.f::<u8>(); + x.collect::<Vec<_>>(); + } + + /// ExprKind::Tup + fn expr_tup() { + (); + (true,); + (true, false); + (true, false,); + } + + /// ExprKind::Binary + fn expr_binary() { + let (a, b, c, d, x, y); + true || false; + true || false && false; + a < 1 && 2 < b && c > 3 && 4 > d; + a & b & !c; + a + b * c - d + -1 * -2 - -3; + x = !y; + } + + /// ExprKind::Unary + fn expr_unary() { + let expr; + *expr; + !expr; + -expr; + } + + /// ExprKind::Lit + fn expr_lit() { + 'x'; + 1_000_i8; + 1.00000000000000000000001; + } + + /// ExprKind::Cast + fn expr_cast() { + let expr; + expr as T; + expr as T<u8>; + } + + /// ExprKind::Type + fn expr_type() { + let expr; + builtin # type_ascribe(expr, T); + } + + /// ExprKind::Let + fn expr_let() { + let b; + if let Some(a) = b {} + if let _ = true && false {} + if let _ = (true && false) {} + } + + /// ExprKind::If + fn expr_if() { + if true {} + if !true {} + if let true = true {} else {} + if true {} else if false {} + if true {} else if false {} else {} + if true { return; } else if false { 0 } else { 0 } + } + + /// ExprKind::While + fn expr_while() { + while false {} + 'a: while false {} + while let true = true {} + } + + /// ExprKind::ForLoop + fn expr_for_loop() { + let x; + for _ in x {} + 'a: for _ in x {} + } + + /// ExprKind::Loop + fn expr_loop() { + loop {} + 'a: loop {} + } + + /// ExprKind::Match + fn expr_match() { + let value; + match value {} + match value { ok => 1 } + match value { + ok => 1, + err => 0, + } + } + + /// ExprKind::Closure + fn expr_closure() { + let value; + || {}; + |x| {}; + |x: u8| {}; + || (); + move || value; + async || value; + async move || value; + static || value; + static move || value; + (static async || value); + (static async move || value); + || -> u8 { value }; + 1 + || {}; + } + + /// ExprKind::Block + fn expr_block() { + {} + unsafe {} + 'a: {} + #[allow()] {} + { #![allow()] } + } + + /// ExprKind::Gen + fn expr_gen() { + async {}; + async move {}; + gen {}; + gen move {}; + async gen {}; + async gen move {}; + } + + /// ExprKind::Await + fn expr_await() { + let fut; + fut.await; + } + + /// ExprKind::TryBlock + fn expr_try_block() { + try {} + try { return; } + } + + /// ExprKind::Assign + fn expr_assign() { + let expr; + expr = true; + } + + /// ExprKind::AssignOp + fn expr_assign_op() { + let expr; + expr += true; + } + + /// ExprKind::Field + fn expr_field() { + let expr; + expr.field; + expr.0; + } + + /// ExprKind::Index + fn expr_index() { + let expr; + expr[true]; + } + + /// ExprKind::Range + fn expr_range() { + let (lo, hi); + ..; + ..hi; + lo..; + lo..hi; + lo .. hi; + ..=hi; + lo..=hi; + -2..=-1; + } + + /// ExprKind::Underscore + fn expr_underscore() { + _; + } + + /// ExprKind::Path + fn expr_path() { + let x; + crate::expressions::expr_path; + crate::expressions::expr_path::<'static>; + <T as Default>::default; + <T as ::core::default::Default>::default::<>; + x::(); + x::(T, T) -> T; + crate::() -> ()::expressions::() -> ()::expr_path; + core::()::marker::()::PhantomData; + } + + /// ExprKind::AddrOf + fn expr_addr_of() { + let expr; + &expr; + &mut expr; + &raw const expr; + &raw mut expr; + } + + /// ExprKind::Break + fn expr_break() { + 'a: { + break; + break 'a; + break true; + break 'a true; + } + } + + /// ExprKind::Continue + fn expr_continue() { + 'a: { + continue; + continue 'a; + } + } + + /// ExprKind::Ret + fn expr_ret() { + return; + return true; + } + + /// ExprKind::InlineAsm + fn expr_inline_asm() { + let x; + core::arch::asm!( + "mov {tmp}, {x}", + "shl {tmp}, 1", + "shl {x}, 2", + "add {x}, {tmp}", + x = inout(reg) x, + tmp = out(reg) _, + ); + } + + /// ExprKind::OffsetOf + fn expr_offset_of() { + core::mem::offset_of!(T, field); + } + + /// ExprKind::MacCall + fn expr_mac_call() { + stringify!(...); + stringify![...]; + stringify! { ... }; + } + + /// ExprKind::Struct + fn expr_struct() { + struct Struct {} + let (x, base); + Struct {}; + <Struct as ToOwned>::Owned {}; + Struct { .. }; + Struct { .. base }; + Struct { x }; + Struct { x, ..base }; + Struct { x: true }; + Struct { x: true, .. }; + Struct { x: true, ..base }; + Struct { 0: true, ..base }; + } + + /// ExprKind::Repeat + fn expr_repeat() { + [(); 0]; + } + + /// ExprKind::Paren + fn expr_paren() { + let expr; + (expr); + } + + /// ExprKind::Try + fn expr_try() { + let expr; + expr?; + } + + /// ExprKind::Yield + fn expr_yield() { + yield; + yield true; + } + + /// ExprKind::Yeet + fn expr_yeet() { + do yeet; + do yeet 0; + } + + /// ExprKind::Become + fn expr_become() { + become true; + } + + /// ExprKind::IncludedBytes + fn expr_include_bytes() { + include_bytes!("auxiliary/data.txt"); + } + + /// ExprKind::FormatArgs + fn expr_format_args() { + let expr; + format_args!(""); + format_args!("{}", expr); + } +} + +mod items { + /// ItemKind::ExternCrate + mod item_extern_crate { + extern crate core; + extern crate self as unpretty; + pub extern crate core as _; + } + + /// ItemKind::Use + mod item_use { + use crate::{expressions, items::item_use}; + pub use core::*; + } + + /// ItemKind::Static + mod item_static { + pub static A: () = {}; + static mut B: () = {}; + } + + /// ItemKind::Const + mod item_const { + pub const A: () = {}; + + trait TraitItems { + const B: (); + const C: () = {}; + } + } + + /// ItemKind::Fn + mod item_fn { + pub const unsafe extern "C" fn f() {} + pub async unsafe extern fn g() {} + fn h<'a, T>() where T: 'a {} + + trait TraitItems { + unsafe extern fn f(); + } + + impl TraitItems for _ { + default unsafe extern fn f() {} + } + } + + /// ItemKind::Mod + mod item_mod { + // ... + } + + /// ItemKind::ForeignMod + mod item_foreign_mod { + extern "C++" {} + extern {} + } + + /// ItemKind::GlobalAsm + mod item_global_asm { + core::arch::global_asm!(".globl my_asm_func"); + } + + /// ItemKind::TyAlias + mod item_ty_alias { + pub type Type<'a> where T: 'a, = T; + } + + /// ItemKind::Enum + mod item_enum { + pub enum Void {} + enum Empty { + Unit, + Tuple(), + Struct {}, + } + enum Generic<'a, T> + where + T: 'a, + { + Tuple(T), + Struct { t: T }, + } + } + + /// ItemKind::Struct + mod item_struct { + pub struct Unit; + struct Tuple(); + struct Newtype(Unit); + struct Struct {} + struct Generic<'a, T> + where + T: 'a, + { + t: T, + } + } + + /// ItemKind::Union + mod item_union { + union Generic<'a, T> + where + T: 'a, + { + t: T, + } + } + + /// ItemKind::Trait + mod item_trait { + pub unsafe auto trait Send {} + trait Trait<'a>: Sized + where + Self: 'a, + { + } + } + + /// ItemKind::TraitAlias + mod item_trait_alias { + pub trait Trait<T> = Sized where for<'a> T: 'a; + } + + /// ItemKind::Impl + mod item_impl { + impl () {} + impl<T> () {} + impl Default for () {} + impl<T> const Default for () {} + } + + /// ItemKind::MacCall + mod item_mac_call { + trace_macros!(false); + trace_macros![false]; + trace_macros! { false } + } + + /// ItemKind::MacroDef + mod item_macro_def { + macro_rules! mac { () => {...}; } + pub macro stringify() {} + } + + /// ItemKind::Delegation + mod item_delegation { + /*! FIXME: todo */ + } + + /// ItemKind::DelegationMac + mod item_delegation_mac { + /*! FIXME: todo */ + } +} + +mod patterns { + /// PatKind::Wild + fn pat_wild() { + let _; + } + + /// PatKind::Ident + fn pat_ident() { + let x; + let ref x; + let mut x; + let ref mut x; + let ref mut x @ _; + } + + /// PatKind::Struct + fn pat_struct() { + let T {}; + let T::<T> {}; + let T::<'static> {}; + let T { x }; + let T { x: _x }; + let T { .. }; + let T { x, .. }; + let T { x: _x, .. }; + let T { 0: _x, .. }; + let <T as ToOwned>::Owned {}; + } + + /// PatKind::TupleStruct + fn pat_tuple_struct() { + struct Tuple(); + let Tuple(); + let Tuple::<T>(); + let Tuple::<'static>(); + let Tuple(x); + let Tuple(..); + let Tuple(x, ..); + } + + /// PatKind::Or + fn pat_or() { + let (true | false); + let (| true); + let (|true| false); + } + + /// PatKind::Path + fn pat_path() { + let core::marker::PhantomData; + let core::marker::PhantomData::<T>; + let core::marker::PhantomData::<'static>; + let <T as Trait>::CONST; + } + + /// PatKind::Tuple + fn pat_tuple() { + let (); + let (true,); + let (true, false); + } + + /// PatKind::Box + fn pat_box() { + let box pat; + } + + /// PatKind::Deref + fn pat_deref() { + let deref!(pat); + } + + /// PatKind::Ref + fn pat_ref() { + let &pat; + let &mut pat; + } + + /// PatKind::Lit + fn pat_lit() { + let 1_000_i8; + let -""; + } + + /// PatKind::Range + fn pat_range() { + let ..1; + let 0..; + let 0..1; + let 0..=1; + let -2..=-1; + } + + /// PatKind::Slice + fn pat_slice() { + let []; + let [true]; + let [true,]; + let [true, false]; + } + + /// PatKind::Rest + fn pat_rest() { + let ..; + } + + /// PatKind::Never + fn pat_never() { + let !; + let Some(!); + } + + /// PatKind::Paren + fn pat_paren() { + let (pat); + } + + /// PatKind::MacCall + fn pat_mac_call() { + let stringify!(); + let stringify![]; + let stringify! {}; + } +} + +mod statements { + /// StmtKind::Let + fn stmt_let() { + let _; + let _ = true; + let _: T = true; + let _ = true else { return; }; + } + + /// StmtKind::Item + fn stmt_item() { + struct Struct {} + struct Unit; + } + + /// StmtKind::Expr + fn stmt_expr() { + () + } + + /// StmtKind::Semi + fn stmt_semi() { + 1 + 1; + } + + /// StmtKind::Empty + fn stmt_empty() { + ; + } + + /// StmtKind::MacCall + fn stmt_mac_call() { + stringify!(...); + stringify![...]; + stringify! { ... }; + } +} + +mod types { + /// TyKind::Slice + fn ty_slice() { + let _: [T]; + } + + /// TyKind::Array + fn ty_array() { + let _: [T; 0]; + } + + /// TyKind::Ptr + fn ty_ptr() { + let _: *const T; + let _: *mut T; + } + + /// TyKind::Ref + fn ty_ref() { + let _: &T; + let _: &mut T; + let _: &'static T; + let _: &'static mut [T]; + let _: &T<T<T<T<T>>>>; + let _: &T<T<T<T<T> > > >; + } + + /// TyKind::BareFn + fn ty_bare_fn() { + let _: fn(); + let _: fn() -> (); + let _: fn(T); + let _: fn(t: T); + let _: for<> fn(); + let _: for<'a> fn(); + } + + /// TyKind::Never + fn ty_never() { + let _: !; + } + + /// TyKind::Tup + fn ty_tup() { + let _: (); + let _: (T,); + let _: (T, T); + } + + /// TyKind::AnonStruct + fn ty_anon_struct() { + struct Struct { + _: struct { t: T }, + } + } + + /// TyKind::AnonUnion + fn ty_anon_union() { + struct Struct { + _: union { t: T }, + } + } + + /// TyKind::Path + fn ty_path() { + let _: T; + let _: T<'static>; + let _: T<T>; + let _: T::<T>; + let _: T() -> !; + let _: <T as ToOwned>::Owned; + } + + /// TyKind::TraitObject + fn ty_trait_object() { + let _: dyn Send; + let _: dyn Send + 'static; + let _: dyn 'static + Send; + let _: dyn for<'a> Send; + } + + /// TyKind::ImplTrait + const fn ty_impl_trait() { + let _: impl Send; + let _: impl Send + 'static; + let _: impl 'static + Send; + let _: impl ?Sized; + let _: impl ~const Clone; + let _: impl for<'a> Send; + } + + /// TyKind::Paren + fn ty_paren() { + let _: (T); + } + + /// TyKind::Typeof + fn ty_typeof() { + /*! unused for now */ + } + + /// TyKind::Infer + fn ty_infer() { + let _: _; + } + + /// TyKind::ImplicitSelf + fn ty_implicit_self() { + /*! there is no syntax for this */ + } + + /// TyKind::MacCall + fn ty_mac_call() { + let _: concat_idents!(T); + let _: concat_idents![T]; + let _: concat_idents! { T }; + } + + /// TyKind::CVarArgs + fn ty_c_var_args() { + /*! FIXME: todo */ + } + + /// TyKind::Pat + fn ty_pat() { + let _: core::pattern_type!(u32 is 1..); + } +} + +mod visibilities { + /// VisibilityKind::Public + mod visibility_public { + pub struct Pub; + } + + /// VisibilityKind::Restricted + mod visibility_restricted { + pub(crate) struct PubCrate; + pub(self) struct PubSelf; + pub(super) struct PubSuper; + pub(in crate) struct PubInCrate; + pub(in self) struct PubInSelf; + pub(in super) struct PubInSuper; + pub(in crate::visibilities) struct PubInCrateVisibilities; + pub(in self::super) struct PubInSelfSuper; + pub(in super::visibility_restricted) struct PubInSuperMod; + } +} diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout new file mode 100644 index 00000000000..325bace7b56 --- /dev/null +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -0,0 +1,719 @@ +#![feature(prelude_import)] +//@ compile-flags: -Zunpretty=expanded -Zunstable-options +//@ edition:2024 +//@ check-pass + +#![feature(async_closure)] +#![feature(auto_traits)] +#![feature(box_patterns)] +#![feature(builtin_syntax)] +#![feature(concat_idents)] +#![feature(const_trait_impl)] +#![feature(core_pattern_type)] +#![feature(decl_macro)] +#![feature(deref_patterns)] +#![feature(explicit_tail_calls)] +#![feature(gen_blocks)] +#![feature(let_chains)] +#![feature(more_qualified_paths)] +#![feature(never_patterns)] +#![feature(never_type)] +#![feature(pattern_types)] +#![feature(prelude_import)] +#![feature(raw_ref_op)] +#![feature(specialization)] +#![feature(trace_macros)] +#![feature(trait_alias)] +#![feature(try_blocks)] +#![feature(unnamed_fields)] +#![feature(yeet_expr)] +#![allow(incomplete_features)] +#[prelude_import] +use std::prelude::rust_2024::*; +#[macro_use] +extern crate std; + +#[prelude_import] +use self::prelude::*; + +mod prelude { + pub use std::prelude::rust_2024::*; + + pub type T = _; + + pub trait Trait { + const CONST: (); + } +} + +mod attributes { + //! inner single-line doc comment + /*! + * inner multi-line doc comment + */ + #![doc = "inner doc attribute"] + #![allow(dead_code, unused_variables)] + #![no_std] + + /// outer single-line doc comment + /** + * outer multi-line doc comment + */ + #[doc = "outer doc attribute"] + #[doc = "macro"] + #[allow()] + #[repr(C)] + struct Struct; +} + +mod expressions { + /// ExprKind::Array + fn expr_array() { + []; + [true]; + [true]; + [true, true]; + ["long........................................................................"]; + ["long............................................................", + true]; + } + + /// ExprKind::ConstBlock + fn expr_const_block() { + const {}; + const { 1 }; + const { + struct S; + }; + } + + /// ExprKind::Call + fn expr_call() { + let f; + f(); + f::<u8>(); + f::<1>(); + f::<'static, u8, 1>(); + f(true); + f(true); + ()(); + } + + /// ExprKind::MethodCall + fn expr_method_call() { + let x; + x.f(); + x.f::<u8>(); + x.collect::<Vec<_>>(); + } + + /// ExprKind::Tup + fn expr_tup() { (); (true,); (true, false); (true, false); } + + /// ExprKind::Binary + fn expr_binary() { + let (a, b, c, d, x, y); + true || false; + true || false && false; + a < 1 && 2 < b && c > 3 && 4 > d; + a & b & !c; + a + b * c - d + -1 * -2 - -3; + x = !y; + } + + /// ExprKind::Unary + fn expr_unary() { let expr; *expr; !expr; -expr; } + + /// ExprKind::Lit + fn expr_lit() { 'x'; 1_000_i8; 1.00000000000000000000001; } + + /// ExprKind::Cast + fn expr_cast() { let expr; expr as T; expr as T<u8>; } + + /// ExprKind::Type + fn expr_type() { let expr; builtin # type_ascribe(expr, T); } + + /// ExprKind::Let + fn expr_let() { + let b; + if let Some(a) = b {} + if let _ = true && false {} + if let _ = (true && false) {} + } + + /// ExprKind::If + fn expr_if() { + if true {} + if !true {} + if let true = true {} else {} + if true {} else if false {} + if true {} else if false {} else {} + if true { return; } else if false { 0 } else { 0 } + } + + /// ExprKind::While + fn expr_while() { + while false {} + 'a: while false {} + while let true = true {} + } + + /// ExprKind::ForLoop + fn expr_for_loop() { let x; for _ in x {} 'a: for _ in x {} } + + /// ExprKind::Loop + fn expr_loop() { loop {} 'a: loop {} } + + /// ExprKind::Match + fn expr_match() { + let value; + match value {} + match value { ok => 1, } + match value { ok => 1, err => 0, } + } + + /// ExprKind::Closure + fn expr_closure() { + let value; + || {}; + |x| {}; + |x: u8| {}; + || (); + move || value; + async || value; + async move || value; + static || value; + static move || value; + (static async || value); + (static async move || value); + || -> u8 { value }; + 1 + (|| {}); + } + + /// ExprKind::Block + fn expr_block() { + {} + unsafe {} + 'a: {} + + #[allow()] + {} + { + #![allow()] + } + } + + /// ExprKind::Gen + fn expr_gen() { + async {}; + async move {}; + gen {}; + gen move {}; + async gen {}; + async gen move {}; + } + + /// ExprKind::Await + fn expr_await() { let fut; fut.await; } + + /// ExprKind::TryBlock + fn expr_try_block() { try {} try { return; } } + + /// ExprKind::Assign + fn expr_assign() { let expr; expr = true; } + + /// ExprKind::AssignOp + fn expr_assign_op() { let expr; expr += true; } + + /// ExprKind::Field + fn expr_field() { let expr; expr.field; expr.0; } + + /// ExprKind::Index + fn expr_index() { let expr; expr[true]; } + + /// ExprKind::Range + fn expr_range() { + let (lo, hi); + ..; + ..hi; + lo..; + lo..hi; + lo..hi; + ..=hi; + lo..=hi; + -2..=-1; + } + + /// ExprKind::Underscore + fn expr_underscore() { _; } + + /// ExprKind::Path + fn expr_path() { + let x; + crate::expressions::expr_path; + crate::expressions::expr_path::<'static>; + <T as Default>::default; + <T as ::core::default::Default>::default::<>; + x::(); + x::(T, T) -> T; + crate::() -> ()::expressions::() -> ()::expr_path; + core::()::marker::()::PhantomData; + } + + /// ExprKind::AddrOf + fn expr_addr_of() { + let expr; + &expr; + &mut expr; + &raw const expr; + &raw mut expr; + } + + /// ExprKind::Break + fn expr_break() { 'a: { break; break 'a; break true; break 'a true; } } + + /// ExprKind::Continue + fn expr_continue() { 'a: { continue; continue 'a; } } + + /// ExprKind::Ret + fn expr_ret() { return; return true; } + + /// ExprKind::InlineAsm + fn expr_inline_asm() { + let x; + asm!("mov {1}, {0}\nshl {1}, 1\nshl {0}, 2\nadd {0}, {1}", + inout(reg) + x, + out(reg) + _); + } + + /// ExprKind::OffsetOf + fn expr_offset_of() { + + + + + + + + + + + + + + + + + + + + // ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { builtin # offset_of(T, field) }; + } + /// ExprKind::MacCall + fn expr_mac_call() { "..."; "..."; "..."; } + /// ExprKind::Struct + fn expr_struct() { + struct Struct {} + let (x, base); + Struct {}; + <Struct as ToOwned>::Owned {}; + Struct { .. }; + Struct { ..base }; + Struct { x }; + Struct { x, ..base }; + Struct { x: true }; + Struct { x: true, .. }; + Struct { x: true, ..base }; + Struct { 0: true, ..base }; + } + /// ExprKind::Repeat + fn expr_repeat() { [(); 0]; } + /// ExprKind::Paren + fn expr_paren() { let expr; (expr); } + /// ExprKind::Try + fn expr_try() { let expr; expr?; } + /// ExprKind::Yield + fn expr_yield() { yield; yield true; } + /// ExprKind::Yeet + fn expr_yeet() { do yeet; do yeet 0; } + /// ExprKind::Become + fn expr_become() { become true; } + /// ExprKind::IncludedBytes + fn expr_include_bytes() { + b"data for include_bytes in ../expanded-exhaustive.rs\n"; + } + /// ExprKind::FormatArgs + fn expr_format_args() { + let expr; + format_args!(""); + format_args!("{0}", expr); + } +} +mod items { + /// ItemKind::ExternCrate + mod item_extern_crate { + extern crate core; + extern crate self as unpretty; + pub extern crate core as _; + } + /// ItemKind::Use + mod item_use { + use crate::{expressions, items::item_use}; + pub use core::*; + } + /// ItemKind::Static + mod item_static { + pub static A: () = {}; + static mut B: () = {}; + } + /// ItemKind::Const + mod item_const { + pub const A: () = {}; + trait TraitItems { + const B: (); + const C: () = {}; + } + } + /// ItemKind::Fn + mod item_fn { + pub const unsafe extern "C" fn f() {} + pub async unsafe extern fn g() {} + fn h<'a, T>() where T: 'a {} + trait TraitItems { + unsafe extern fn f(); + } + impl TraitItems for _ { + default unsafe extern fn f() {} + } + } + /// ItemKind::Mod + mod item_mod { } + /// ItemKind::ForeignMod + mod item_foreign_mod { + extern "C++" {} + extern {} + } + /// ItemKind::GlobalAsm + mod item_global_asm { + global_asm! (".globl my_asm_func"); + } + /// ItemKind::TyAlias + mod item_ty_alias { + pub type Type<'a> where T: 'a = T; + } + /// ItemKind::Enum + mod item_enum { + pub enum Void {} + enum Empty { Unit, Tuple(), Struct {}, } + enum Generic<'a, T> where T: 'a { + Tuple(T), + Struct { + t: T, + }, + } + } + /// ItemKind::Struct + mod item_struct { + pub struct Unit; + struct Tuple(); + struct Newtype(Unit); + struct Struct {} + struct Generic<'a, T> where T: 'a { + t: T, + } + } + /// ItemKind::Union + mod item_union { + union Generic<'a, T> where T: 'a { + t: T, + } + } + /// ItemKind::Trait + mod item_trait { + pub unsafe auto trait Send {} + trait Trait<'a>: Sized where Self: 'a {} + } + /// ItemKind::TraitAlias + mod item_trait_alias { + pub trait Trait<T> = Sized where for<'a> T: 'a; + } + /// ItemKind::Impl + mod item_impl { + impl () {} + impl<T> () {} + impl Default for () {} + impl<T> const Default for () {} + } + /// ItemKind::MacCall + mod item_mac_call { } + /// ItemKind::MacroDef + mod item_macro_def { + macro_rules! mac { () => { ... }; } + pub macro stringify { () => {} } + } + /// ItemKind::Delegation + mod item_delegation { + /*! FIXME: todo */ + } + /// ItemKind::DelegationMac + mod item_delegation_mac { + /*! FIXME: todo */ + } +} +mod patterns { + /// PatKind::Wild + fn pat_wild() { let _; } + /// PatKind::Ident + fn pat_ident() { + let x; + let ref x; + let mut x; + let ref mut x; + let ref mut x @ _; + } + /// PatKind::Struct + fn pat_struct() { + let T {}; + let T::<T> {}; + let T::<'static> {}; + let T { x }; + let T { x: _x }; + let T { .. }; + let T { x, .. }; + let T { x: _x, .. }; + let T { 0: _x, .. }; + let <T as ToOwned>::Owned {}; + } + /// PatKind::TupleStruct + fn pat_tuple_struct() { + struct Tuple(); + let Tuple(); + let Tuple::<T>(); + let Tuple::<'static>(); + let Tuple(x); + let Tuple(..); + let Tuple(x, ..); + } + /// PatKind::Or + fn pat_or() { let (true | false); let (true); let (true | false); } + /// PatKind::Path + fn pat_path() { + let core::marker::PhantomData; + let core::marker::PhantomData::<T>; + let core::marker::PhantomData::<'static>; + let <T as Trait>::CONST; + } + /// PatKind::Tuple + fn pat_tuple() { let (); let (true,); let (true, false); } + /// PatKind::Box + fn pat_box() { let box pat; } + /// PatKind::Deref + fn pat_deref() { let deref!(pat); } + /// PatKind::Ref + fn pat_ref() { let &pat; let &mut pat; } + /// PatKind::Lit + fn pat_lit() { let 1_000_i8; let -""; } + /// PatKind::Range + fn pat_range() { let ..1; let 0..; let 0..1; let 0..=1; let -2..=-1; } + /// PatKind::Slice + fn pat_slice() { let []; let [true]; let [true]; let [true, false]; } + /// PatKind::Rest + fn pat_rest() { let ..; } + /// PatKind::Never + fn pat_never() { let !; let Some(!); } + /// PatKind::Paren + fn pat_paren() { let (pat); } + /// PatKind::MacCall + fn pat_mac_call() { let ""; let ""; let ""; } +} +mod statements { + /// StmtKind::Let + fn stmt_let() { + let _; + let _ = true; + let _: T = true; + let _ = true else { return; }; + } + /// StmtKind::Item + fn stmt_item() { + struct Struct {} + struct Unit; + } + /// StmtKind::Expr + fn stmt_expr() { () } + /// StmtKind::Semi + fn stmt_semi() { 1 + 1; } + /// StmtKind::Empty + fn stmt_empty() { ; } + /// StmtKind::MacCall + fn stmt_mac_call() { "..."; "..."; "..."; } +} +mod types { + /// TyKind::Slice + fn ty_slice() { let _: [T]; } + /// TyKind::Array + fn ty_array() { let _: [T; 0]; } + /// TyKind::Ptr + fn ty_ptr() { let _: *const T; let _: *mut T; } + /// TyKind::Ref + fn ty_ref() { + let _: &T; + let _: &mut T; + let _: &'static T; + let _: &'static mut [T]; + let _: &T<T<T<T<T>>>>; + let _: &T<T<T<T<T>>>>; + } + /// TyKind::BareFn + fn ty_bare_fn() { + let _: fn(); + let _: fn() -> (); + let _: fn(T); + let _: fn(t: T); + let _: fn(); + let _: for<'a> fn(); + } + /// TyKind::Never + fn ty_never() { let _: !; } + /// TyKind::Tup + fn ty_tup() { let _: (); let _: (T,); let _: (T, T); } + /// TyKind::AnonStruct + fn ty_anon_struct() { + struct Struct { + _: struct { + t: T, + }, + } + } + /// TyKind::AnonUnion + fn ty_anon_union() { + struct Struct { + _: union { + t: T, + }, + } + } + /// TyKind::Path + fn ty_path() { + let _: T; + let _: T<'static>; + let _: T<T>; + let _: T<T>; + let _: T() -> !; + let _: <T as ToOwned>::Owned; + } + /// TyKind::TraitObject + fn ty_trait_object() { + let _: dyn Send; + let _: dyn Send + 'static; + let _: dyn 'static + Send; + let _: dyn for<'a> Send; + } + /// TyKind::ImplTrait + const fn ty_impl_trait() { + let _: impl Send; + let _: impl Send + 'static; + let _: impl 'static + Send; + let _: impl ?Sized; + let _: impl ~const Clone; + let _: impl for<'a> Send; + } + /// TyKind::Paren + fn ty_paren() { let _: (T); } + /// TyKind::Typeof + fn ty_typeof() { + /*! unused for now */ + } + /// TyKind::Infer + fn ty_infer() { let _: _; } + /// TyKind::ImplicitSelf + fn ty_implicit_self() { + /*! there is no syntax for this */ + } + /// TyKind::MacCall + fn ty_mac_call() { let _: T; let _: T; let _: T; } + /// TyKind::CVarArgs + fn ty_c_var_args() { + /*! FIXME: todo */ + } + /// TyKind::Pat + fn ty_pat() { let _: u32 is 1..; } +} +mod visibilities { + /// VisibilityKind::Public + mod visibility_public { + pub struct Pub; + } + /// VisibilityKind::Restricted + mod visibility_restricted { + pub(crate) struct PubCrate; + pub(self) struct PubSelf; + pub(super) struct PubSuper; + pub(in crate) struct PubInCrate; + pub(in self) struct PubInSelf; + pub(in super) struct PubInSuper; + pub(in crate::visibilities) struct PubInCrateVisibilities; + pub(in self::super) struct PubInSelfSuper; + pub(in super::visibility_restricted) struct PubInSuperMod; + } +} diff --git a/tests/ui/unpretty/expanded-interpolation.rs b/tests/ui/unpretty/expanded-interpolation.rs new file mode 100644 index 00000000000..8f0e21ce870 --- /dev/null +++ b/tests/ui/unpretty/expanded-interpolation.rs @@ -0,0 +1,106 @@ +//@ compile-flags: -Zunpretty=expanded +//@ check-pass + +// This test covers the AST pretty-printer's insertion of parentheses in some +// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in +// the syntax tree) need to be printed in order for the printed code to be valid +// Rust syntax. We also test negative cases: the pretty-printer should not be +// synthesizing parentheses indiscriminately; only where necessary. + +#![feature(let_chains)] +#![feature(if_let_guard)] + +macro_rules! expr { + ($expr:expr) => { $expr }; +} + +macro_rules! stmt { + ($stmt:stmt) => { $stmt }; +} + +fn if_let() { + macro_rules! if_let { + ($pat:pat, $expr:expr) => { + if let $pat = $expr {} + }; + } + + if let no_paren = true && false {} + if_let!(paren_around_binary, true && false); + if_let!(no_paren, true); + + struct Struct {} + match () { + _ if let no_paren = Struct {} => {} + } +} + +fn let_else() { + let no_paren = expr!(1 + 1) else { return; }; + let paren_around_loop = expr!(loop {}) else { return; }; +} + +fn local() { + macro_rules! let_expr_minus_one { + ($pat:pat, $expr:expr) => { + let $pat = $expr - 1; + }; + } + + let void; + let_expr_minus_one!(no_paren, match void {}); + + macro_rules! let_expr_else_return { + ($pat:pat, $expr:expr) => { + let $pat = $expr else { return; }; + }; + } + + let_expr_else_return!(no_paren, void()); +} + +fn match_arm() { + macro_rules! match_arm { + ($pat:pat, $expr:expr) => { + match () { $pat => $expr } + }; + } + + match_arm!(no_paren, 1 - 1); + match_arm!(paren_around_brace, { 1 } - 1); +} + +/// https://github.com/rust-lang/rust/issues/98790 +fn stmt_boundary() { + macro_rules! expr_as_stmt { + ($expr:expr) => { + stmt!($expr) + }; + } + + let paren_around_match; + expr_as_stmt!(match paren_around_match {} | true); + + macro_rules! minus_one { + ($expr:expr) => { + expr_as_stmt!($expr - 1) + }; + } + + let (no_paren, paren_around_loop); + minus_one!(no_paren); + minus_one!(match paren_around_match {}); + minus_one!(match paren_around_match {}()); + minus_one!(match paren_around_match {}[0]); + minus_one!(loop { break paren_around_loop; }); +} + +fn vis_inherited() { + macro_rules! vis_inherited { + ($vis:vis struct) => { + $vis struct Struct; + }; + } + + vis_inherited!(struct); +} diff --git a/tests/ui/unpretty/expanded-interpolation.stdout b/tests/ui/unpretty/expanded-interpolation.stdout new file mode 100644 index 00000000000..73322b50f2d --- /dev/null +++ b/tests/ui/unpretty/expanded-interpolation.stdout @@ -0,0 +1,92 @@ +#![feature(prelude_import)] +#![no_std] +//@ compile-flags: -Zunpretty=expanded +//@ check-pass + +// This test covers the AST pretty-printer's insertion of parentheses in some +// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in +// the syntax tree) need to be printed in order for the printed code to be valid +// Rust syntax. We also test negative cases: the pretty-printer should not be +// synthesizing parentheses indiscriminately; only where necessary. + +#![feature(let_chains)] +#![feature(if_let_guard)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +macro_rules! expr { ($expr:expr) => { $expr }; } + +macro_rules! stmt { ($stmt:stmt) => { $stmt }; } + +fn if_let() { + macro_rules! if_let { + ($pat:pat, $expr:expr) => { if let $pat = $expr {} }; + } + + if let no_paren = true && false {} + if let paren_around_binary = (true && false) {}; + if let no_paren = true {}; + + struct Struct {} + match () { _ if let no_paren = Struct {} => {} } +} + +fn let_else() { + let no_paren = 1 + 1 else { return; }; + let paren_around_loop = (loop {}) else { return; }; +} + +fn local() { + macro_rules! let_expr_minus_one { + ($pat:pat, $expr:expr) => { let $pat = $expr - 1; }; + } + + let void; + let no_paren = match void {} - 1; + + macro_rules! let_expr_else_return { + ($pat:pat, $expr:expr) => { let $pat = $expr else { return; }; }; + } + let + + no_paren = void() else { return; }; +} + +fn match_arm() { + macro_rules! match_arm { + ($pat:pat, $expr:expr) => { match () { $pat => $expr } }; + } + match () { + + + no_paren => 1 - 1, + }; + match () { paren_around_brace => ({ 1 }) - 1, }; +} + +/// https://github.com/rust-lang/rust/issues/98790 +fn stmt_boundary() { + macro_rules! expr_as_stmt { ($expr:expr) => { stmt!($expr) }; } + + let paren_around_match; + (match paren_around_match {}) | true; + + macro_rules! minus_one { ($expr:expr) => { expr_as_stmt!($expr - 1) }; } + + let (no_paren, paren_around_loop); + no_paren - 1; + (match paren_around_match {}) - 1; + (match paren_around_match {})() - 1; + (match paren_around_match {})[0] - 1; + (loop { break paren_around_loop; }) - 1; +} + +fn vis_inherited() { + macro_rules! vis_inherited { + ($vis:vis struct) => { $vis struct Struct; }; + } + struct Struct; + +} diff --git a/tests/ui/unpretty/let-else.rs b/tests/ui/unpretty/let-else.rs deleted file mode 100644 index 4db6eca99b1..00000000000 --- a/tests/ui/unpretty/let-else.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ compile-flags: -Zunpretty=expanded -//@ check-pass - -macro_rules! expr { - ($e:expr) => { $e }; -} - -fn main() { - let _ = expr!(1 + 1) else { return; }; - let _ = expr!(loop {}) else { return; }; -} diff --git a/tests/ui/unpretty/let-else.stdout b/tests/ui/unpretty/let-else.stdout deleted file mode 100644 index 4bc4d9e085f..00000000000 --- a/tests/ui/unpretty/let-else.stdout +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(prelude_import)] -#![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; -#[macro_use] -extern crate std; -//@ compile-flags: -Zunpretty=expanded -//@ check-pass - -macro_rules! expr { ($e:expr) => { $e }; } - -fn main() { - let _ = 1 + 1 else { return; }; - let _ = (loop {}) else { return; }; -} diff --git a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr b/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr index 23bfe3c9c2e..abd59bdbc75 100644 --- a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr +++ b/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/ranged-ctor-as-fn-ptr.rs:8:40 | LL | let x: fn(u8) -> NonZeroAndOneU8 = NonZeroAndOneU8; - | ------------------------- ^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn + | ------------------------- ^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn | | | expected due to this | diff --git a/tests/ui/unsafe/unsafe-subtyping.stderr b/tests/ui/unsafe/unsafe-subtyping.stderr index 1cc949cf757..ddeeaa51202 100644 --- a/tests/ui/unsafe/unsafe-subtyping.stderr +++ b/tests/ui/unsafe/unsafe-subtyping.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(x: Option<fn(i32)>) -> Option<unsafe fn(i32)> { | ---------------------- expected `Option<unsafe fn(i32)>` because of return type LL | x - | ^ expected unsafe fn, found normal fn + | ^ expected unsafe fn, found safe fn | = note: expected enum `Option<unsafe fn(_)>` found enum `Option<fn(_)>` diff --git a/tests/ui/unsafe/unsafe-trait-impl.stderr b/tests/ui/unsafe/unsafe-trait-impl.stderr index 5888b674d4f..b9f2e1cc869 100644 --- a/tests/ui/unsafe/unsafe-trait-impl.stderr +++ b/tests/ui/unsafe/unsafe-trait-impl.stderr @@ -2,7 +2,7 @@ error[E0053]: method `len` has an incompatible type for trait --> $DIR/unsafe-trait-impl.rs:8:5 | LL | fn len(&self) -> u32 { *self } - | ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn + | ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found safe fn | note: type in trait --> $DIR/unsafe-trait-impl.rs:4:5 diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 599b1f3d45e..1e898fb7b78 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -1,30 +1,37 @@ -error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed - --> $DIR/wf-normalization-sized.rs:19:10 +error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time + --> $DIR/wf-normalization-sized.rs:19:11 | LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` -error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed - --> $DIR/wf-normalization-sized.rs:19:10 +error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time + --> $DIR/wf-normalization-sized.rs:19:11 | LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed - --> $DIR/wf-normalization-sized.rs:22:10 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/wf-normalization-sized.rs:22:11 | LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` -error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed - --> $DIR/wf-normalization-sized.rs:22:10 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/wf-normalization-sized.rs:22:11 | LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ doesn't have a size known at compile-time | + = help: the trait `Sized` is not implemented for `str` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-normalization-sized.rs b/tests/ui/wf/wf-normalization-sized.rs index e6e24ff9e85..80b2c8803ff 100644 --- a/tests/ui/wf/wf-normalization-sized.rs +++ b/tests/ui/wf/wf-normalization-sized.rs @@ -17,10 +17,10 @@ impl<T: ?Sized> WellUnformed for T { } const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); -//[next]~^ the type -//[next]~| the type +//[next]~^ the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time +//[next]~| the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time const _: <Vec<str> as WellUnformed>::RequestNormalize = (); -//[next]~^ the type -//[next]~| the type +//[next]~^ the size for values of type `str` cannot be known at compilation time +//[next]~| the size for values of type `str` cannot be known at compilation time fn main() {} diff --git a/triagebot.toml b/triagebot.toml index 80820d2f297..2e45b257f81 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -867,6 +867,7 @@ compiler-team-contributors = [ "@fmease", "@fee1-dead", "@jieyouxu", + "@BoxyUwU", ] compiler = [ "compiler-team", |
