diff options
Diffstat (limited to 'compiler')
148 files changed, 1692 insertions, 949 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 114b9835b98..4ace80a7344 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -308,7 +308,6 @@ impl ParenthesizedArgs { } } -use crate::AstDeref; pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId}; /// Modifiers on a trait bound like `~const`, `?` and `!`. @@ -2349,7 +2348,7 @@ impl Ty { pub fn is_maybe_parenthesised_infer(&self) -> bool { match &self.kind { TyKind::Infer => true, - TyKind::Paren(inner) => inner.ast_deref().is_maybe_parenthesised_infer(), + TyKind::Paren(inner) => inner.is_maybe_parenthesised_infer(), _ => false, } } diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 7f98e7ba8a6..21de7ff7719 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -13,34 +13,6 @@ use crate::{ Ty, Variant, Visibility, WherePredicate, }; -/// A utility trait to reduce boilerplate. -/// Standard `Deref(Mut)` cannot be reused due to coherence. -pub trait AstDeref { - type Target; - fn ast_deref(&self) -> &Self::Target; - fn ast_deref_mut(&mut self) -> &mut Self::Target; -} - -macro_rules! impl_not_ast_deref { - ($($T:ty),+ $(,)?) => { - $( - impl !AstDeref for $T {} - )+ - }; -} - -impl_not_ast_deref!(AssocItem, Expr, ForeignItem, Item, Stmt); - -impl<T> AstDeref for P<T> { - type Target = T; - fn ast_deref(&self) -> &Self::Target { - self - } - fn ast_deref_mut(&mut self) -> &mut Self::Target { - self - } -} - /// A trait for AST nodes having an ID. pub trait HasNodeId { fn node_id(&self) -> NodeId; @@ -81,12 +53,12 @@ impl_has_node_id!( WherePredicate, ); -impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T { +impl<T: HasNodeId> HasNodeId for P<T> { fn node_id(&self) -> NodeId { - self.ast_deref().node_id() + (**self).node_id() } fn node_id_mut(&mut self) -> &mut NodeId { - self.ast_deref_mut().node_id_mut() + (**self).node_id_mut() } } @@ -138,21 +110,21 @@ impl_has_tokens_none!( WherePredicate ); -impl<T: AstDeref<Target: HasTokens>> HasTokens for T { +impl<T: HasTokens> HasTokens for Option<T> { fn tokens(&self) -> Option<&LazyAttrTokenStream> { - self.ast_deref().tokens() + self.as_ref().and_then(|inner| inner.tokens()) } fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> { - self.ast_deref_mut().tokens_mut() + self.as_mut().and_then(|inner| inner.tokens_mut()) } } -impl<T: HasTokens> HasTokens for Option<T> { +impl<T: HasTokens> HasTokens for P<T> { fn tokens(&self) -> Option<&LazyAttrTokenStream> { - self.as_ref().and_then(|inner| inner.tokens()) + (**self).tokens() } fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> { - self.as_mut().and_then(|inner| inner.tokens_mut()) + (**self).tokens_mut() } } @@ -273,13 +245,13 @@ impl_has_attrs!( ); impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility); -impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T { - const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::Target::SUPPORTS_CUSTOM_INNER_ATTRS; +impl<T: HasAttrs> HasAttrs for P<T> { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS; fn attrs(&self) -> &[Attribute] { - self.ast_deref().attrs() + (**self).attrs() } fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { - self.ast_deref_mut().visit_attrs(f) + (**self).visit_attrs(f); } } @@ -343,13 +315,22 @@ impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> { } } -impl<Wrapped, Tag> AstDeref for AstNodeWrapper<Wrapped, Tag> { - type Target = Wrapped; - fn ast_deref(&self) -> &Self::Target { - &self.wrapped +impl<Wrapped: HasNodeId, Tag> HasNodeId for AstNodeWrapper<Wrapped, Tag> { + fn node_id(&self) -> NodeId { + self.wrapped.node_id() + } + fn node_id_mut(&mut self) -> &mut NodeId { + self.wrapped.node_id_mut() + } +} + +impl<Wrapped: HasAttrs, Tag> HasAttrs for AstNodeWrapper<Wrapped, Tag> { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = Wrapped::SUPPORTS_CUSTOM_INNER_ATTRS; + fn attrs(&self) -> &[Attribute] { + self.wrapped.attrs() } - fn ast_deref_mut(&mut self) -> &mut Self::Target { - &mut self.wrapped + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { + self.wrapped.visit_attrs(f); } } diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index e572ec99dab..89a5a67eb53 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(deny(warnings))) @@ -46,7 +45,7 @@ pub mod tokenstream; pub mod visit; pub use self::ast::*; -pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens}; +pub use self::ast_traits::{AstNodeWrapper, HasAttrs, HasNodeId, HasTokens}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8597820073a..19095f2e01e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,7 +32,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -896,7 +895,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ret = self.arena.alloc_from_iter(lowered_attrs); // this is possible if an item contained syntactical attribute, - // but none of them parse succesfully or all of them were ignored + // but none of them parse successfully or all of them were ignored // for not being built-in attributes at all. They could be remaining // unexpanded attributes used as markers in proc-macro derives for example. // This will have emitted some diagnostics for the misparse, but will then diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 7956057f88e..6517fdb55bd 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,7 +4,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index 679fe935484..dbfc95b047a 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(rustdoc_internals)] // tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index d37ede86cfd..c1d95d07f4c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -53,7 +53,7 @@ fn parse_unstable<'a>( for param in list.mixed() { let param_span = param.span(); - if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) { + if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) { res.push(ident.name); } else { cx.emit_err(session_diagnostics::ExpectsFeatures { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 7d1417446b2..fb3d5f57d4f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,5 +1,4 @@ use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation}; -use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol, sym}; use super::SingleAttributeParser; @@ -13,16 +12,13 @@ pub(crate) struct DeprecationParser; fn get( cx: &AcceptContext<'_>, - ident: Ident, + name: Symbol, param_span: Span, arg: &ArgParser<'_>, item: &Option<Symbol>, ) -> Option<Symbol> { if item.is_some() { - cx.emit_err(session_diagnostics::MultipleItem { - span: param_span, - item: ident.to_string(), - }); + cx.emit_err(session_diagnostics::MultipleItem { span: param_span, item: name.to_string() }); return None; } if let Some(v) = arg.name_value() { @@ -83,16 +79,16 @@ impl SingleAttributeParser for DeprecationParser { return None; }; - let (ident, arg) = param.word_or_empty(); + let ident_name = param.path_without_args().word_sym(); - match ident.name { - sym::since => { - since = Some(get(cx, ident, param_span, arg, &since)?); + match ident_name { + Some(name @ sym::since) => { + since = Some(get(cx, name, param_span, param.args(), &since)?); } - sym::note => { - note = Some(get(cx, ident, param_span, arg, ¬e)?); + Some(name @ sym::note) => { + note = Some(get(cx, name, param_span, param.args(), ¬e)?); } - sym::suggestion => { + Some(name @ sym::suggestion) => { if !features.deprecated_suggestion() { cx.emit_err(session_diagnostics::DeprecatedItemSuggestion { span: param_span, @@ -101,12 +97,12 @@ impl SingleAttributeParser for DeprecationParser { }); } - suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?); + suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?); } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, - item: ident.to_string(), + item: param.path_without_args().to_string(), expected: if features.deprecated_suggestion() { &["since", "note", "suggestion"] } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 26ca637faec..43dfb85a7c4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -96,58 +96,75 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the // structure. - let (ident, args) = param.word_or_empty(); + let (name, ident_span) = if let Some(ident) = param.path_without_args().word() { + (Some(ident.name), ident.span) + } else { + (None, rustc_span::DUMMY_SP) + }; + + let args = param.args(); - match (ident.name, args) { - (sym::align, ArgParser::NoArgs) => { - cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span }); + match (name, args) { + (Some(sym::align), ArgParser::NoArgs) => { + cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span }); None } - (sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align), + (Some(sym::align), ArgParser::List(l)) => { + parse_repr_align(cx, l, param.span(), AlignKind::Align) + } - (sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), - (sym::packed, ArgParser::List(l)) => { + (Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), + (Some(sym::packed), ArgParser::List(l)) => { parse_repr_align(cx, l, param.span(), AlignKind::Packed) } - (sym::align | sym::packed, ArgParser::NameValue(l)) => { + (Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => { cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric { span: param.span(), // FIXME(jdonszelmann) can just be a string in the diag type - repr_arg: &ident.to_string(), + repr_arg: name, cause: IncorrectReprFormatGenericCause::from_lit_kind( param.span(), &l.value_as_lit().kind, - ident.name.as_str(), + name, ), }); None } - (sym::Rust, ArgParser::NoArgs) => Some(ReprRust), - (sym::C, ArgParser::NoArgs) => Some(ReprC), - (sym::simd, ArgParser::NoArgs) => Some(ReprSimd), - (sym::transparent, ArgParser::NoArgs) => Some(ReprTransparent), - (i @ int_pat!(), ArgParser::NoArgs) => { + (Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust), + (Some(sym::C), ArgParser::NoArgs) => Some(ReprC), + (Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd), + (Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent), + (Some(name @ int_pat!()), ArgParser::NoArgs) => { // int_pat!() should make sure it always parses - Some(ReprInt(int_type_of_word(i).unwrap())) + Some(ReprInt(int_type_of_word(name).unwrap())) } ( - sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), + Some( + name @ sym::Rust + | name @ sym::C + | name @ sym::simd + | name @ sym::transparent + | name @ int_pat!(), + ), ArgParser::NameValue(_), ) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoValue { - span: param.span(), - name: ident.to_string(), - }); + cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name }); None } - (sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoParen { - span: param.span(), - name: ident.to_string(), - }); + ( + Some( + name @ sym::Rust + | name @ sym::C + | name @ sym::simd + | name @ sym::transparent + | name @ int_pat!(), + ), + ArgParser::List(_), + ) => { + cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name }); None } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index bdad6b50186..cd1f21d92e7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -242,9 +242,9 @@ pub(crate) fn parse_stability( return None; }; - match param.word_or_empty_without_args().name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::since => insert_value_into_option_or_error(cx, ¶m, &mut since)?, + match param.path_without_args().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &mut since)?, _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, @@ -310,11 +310,10 @@ pub(crate) fn parse_unstability( return None; }; - let (word, args) = param.word_or_empty(); - match word.name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::reason => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, - sym::issue => { + match param.path_without_args().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, + Some(sym::issue) => { insert_value_into_option_or_error(cx, ¶m, &mut issue)?; // These unwraps are safe because `insert_value_into_option_or_error` ensures the meta item @@ -328,7 +327,7 @@ pub(crate) fn parse_unstability( session_diagnostics::InvalidIssueString { span: param.span(), cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind( - args.name_value().unwrap().value_span, + param.args().name_value().unwrap().value_span, err.kind(), ), }, @@ -338,13 +337,15 @@ pub(crate) fn parse_unstability( }, }; } - sym::soft => { - if !args.no_args() { + Some(sym::soft) => { + if !param.args().no_args() { cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() }); } is_soft = true; } - sym::implied_by => insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?, + Some(sym::implied_by) => { + insert_value_into_option_or_error(cx, ¶m, &mut implied_by)? + } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param.span(), diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 874fccf7ff6..177df356742 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -77,7 +77,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(rustdoc_internals)] #![recursion_limit = "256"] diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 40aa39711d3..077d953cfa3 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -78,8 +78,8 @@ impl<'a> PathParser<'a> { (self.len() == 1).then(|| **self.segments().next().as_ref().unwrap()) } - pub fn word_or_empty(&self) -> Ident { - self.word().unwrap_or_else(Ident::empty) + pub fn word_sym(&self) -> Option<Symbol> { + self.word().map(|ident| ident.name) } /// Asserts that this MetaItem is some specific word. @@ -284,11 +284,6 @@ impl<'a> MetaItemParser<'a> { Some(self.word()?.0) } - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty_without_args(&self) -> Ident { - self.word_or_empty().0 - } - /// Asserts that this MetaItem starts with a word, or single segment path. /// /// Some examples: @@ -300,12 +295,6 @@ impl<'a> MetaItemParser<'a> { Some((path.word()?, args)) } - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty(&self) -> (Ident, &ArgParser<'a>) { - let (path, args) = self.deconstruct(); - (path.word().unwrap_or(Ident::empty()), args) - } - /// Asserts that this MetaItem starts with some specific word. /// /// See [`word`](Self::word) for examples of what a word is. diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 9d34b807ac2..2c434175b4b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -204,7 +204,7 @@ pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, - pub name: String, + pub name: Symbol, } #[derive(Diagnostic)] @@ -213,7 +213,7 @@ pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, - pub name: String, + pub name: Symbol, } /// Error code: E0565 @@ -295,21 +295,21 @@ pub(crate) struct IncorrectReprFormatExpectInteger { #[derive(Diagnostic)] #[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)] -pub(crate) struct IncorrectReprFormatGeneric<'a> { +pub(crate) struct IncorrectReprFormatGeneric { #[primary_span] pub span: Span, - pub repr_arg: &'a str, + pub repr_arg: Symbol, #[subdiagnostic] - pub cause: Option<IncorrectReprFormatGenericCause<'a>>, + pub cause: Option<IncorrectReprFormatGenericCause>, } #[derive(Subdiagnostic)] -pub(crate) enum IncorrectReprFormatGenericCause<'a> { +pub(crate) enum IncorrectReprFormatGenericCause { #[suggestion( attr_parsing_suggestion, - code = "{name}({int})", + code = "{name}({value})", applicability = "machine-applicable" )] Int { @@ -317,15 +317,15 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { span: Span, #[skip_arg] - name: &'a str, + name: Symbol, #[skip_arg] - int: u128, + value: u128, }, #[suggestion( attr_parsing_suggestion, - code = "{name}({symbol})", + code = "{name}({value})", applicability = "machine-applicable" )] Symbol { @@ -333,20 +333,20 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { span: Span, #[skip_arg] - name: &'a str, + name: Symbol, #[skip_arg] - symbol: Symbol, + value: Symbol, }, } -impl<'a> IncorrectReprFormatGenericCause<'a> { - pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> { - match kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - Some(Self::Int { span, name, int: int.get() }) +impl IncorrectReprFormatGenericCause { + pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option<Self> { + match *kind { + ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => { + Some(Self::Int { span, name, value: value.get() }) } - ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }), + ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }), _ => None, } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3e075d420a3..676cb618b72 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,7 +2,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs index d41cbf757d7..341c50c37f6 100644 --- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs +++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs @@ -266,10 +266,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 0913dc91a53..f3ac932e1b7 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -8,7 +8,7 @@ use std::env::VarError; use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability}; +use rustc_ast::{ExprKind, GenericArg, Mutability}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::{Ident, Span, Symbol, kw, sym}; use thin_vec::thin_vec; @@ -148,13 +148,13 @@ pub(crate) fn expand_env<'cx>( cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar { span, var: *symbol, - var_expr: var_expr.ast_deref(), + var_expr: &var_expr, }) } else { cx.dcx().emit_err(errors::EnvNotDefined::CustomEnvVar { span, var: *symbol, - var_expr: var_expr.ast_deref(), + var_expr: &var_expr, }) } } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index c2f5bf0f457..9cd4d17059a 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,7 +5,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index e866b896255..9018d78b00a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1109,6 +1109,43 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::minimumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::minimumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::maximumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::maximumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::minnumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 6720f6186d1..9e5ebf3a9a4 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -2454,7 +2454,6 @@ impl ToGccOrdering for AtomicOrdering { use MemOrdering::*; let ordering = match self { - AtomicOrdering::Unordered => __ATOMIC_RELAXED, AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same. AtomicOrdering::Acquire => __ATOMIC_ACQUIRE, AtomicOrdering::Release => __ATOMIC_RELEASE, diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 2ed5ec4381e..9caceca9295 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -74,8 +74,44 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", sym::minnumf64 => "fmin", + sym::minimumf32 => "fminimumf", + sym::minimumf64 => "fminimum", + sym::minimumf128 => { + // GCC doesn't have the intrinsic we want so we use the compiler-builtins one + // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html + let f128_type = cx.type_f128(); + return Some(cx.context.new_function( + None, + FunctionType::Extern, + f128_type, + &[ + cx.context.new_parameter(None, f128_type, "a"), + cx.context.new_parameter(None, f128_type, "b"), + ], + "fminimumf128", + false, + )); + } sym::maxnumf32 => "fmaxf", sym::maxnumf64 => "fmax", + sym::maximumf32 => "fmaximumf", + sym::maximumf64 => "fmaximum", + sym::maximumf128 => { + // GCC doesn't have the intrinsic we want so we use the compiler-builtins one + // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html + let f128_type = cx.type_f128(); + return Some(cx.context.new_function( + None, + FunctionType::Extern, + f128_type, + &[ + cx.context.new_parameter(None, f128_type, "a"), + cx.context.new_parameter(None, f128_type, "b"), + ], + "fmaximumf128", + false, + )); + } sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", sym::copysignf128 => "copysignl", diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index e481b99afcc..9e3893d5314 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -14,7 +14,7 @@ use smallvec::SmallVec; use tracing::debug; use crate::builder::Builder; -use crate::common::{AsCCharPtr, Funclet}; +use crate::common::Funclet; use crate::context::CodegenCx; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; @@ -435,13 +435,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { template_str.push_str("\n.att_syntax\n"); } - unsafe { - llvm::LLVMAppendModuleInlineAsm( - self.llmod, - template_str.as_c_char_ptr(), - template_str.len(), - ); - } + llvm::append_module_inline_asm(self.llmod, template_str.as_bytes()); } fn mangled_name(&self, instance: Instance<'tcx>) -> String { @@ -482,67 +476,67 @@ pub(crate) fn inline_asm_call<'ll>( debug!("Asm Output Type: {:?}", output); let fty = bx.cx.type_func(&argtys, output); + // Ask LLVM to verify that the constraints are well-formed. - let constraints_ok = - unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len()) }; + let constraints_ok = unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr(), cons.len()) }; debug!("constraint verification result: {:?}", constraints_ok); - if constraints_ok { - let v = unsafe { - llvm::LLVMRustInlineAsm( - fty, - asm.as_c_char_ptr(), - asm.len(), - cons.as_c_char_ptr(), - cons.len(), - volatile, - alignstack, - dia, - can_throw, - ) - }; + if !constraints_ok { + // LLVM has detected an issue with our constraints, so bail out. + return None; + } - let call = if !labels.is_empty() { - assert!(catch_funclet.is_none()); - bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None) - } else if let Some((catch, funclet)) = catch_funclet { - bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None) - } else { - bx.call(fty, None, None, v, inputs, None, None) - }; + let v = unsafe { + llvm::LLVMGetInlineAsm( + fty, + asm.as_ptr(), + asm.len(), + cons.as_ptr(), + cons.len(), + volatile, + alignstack, + dia, + can_throw, + ) + }; - // Store mark in a metadata node so we can map LLVM errors - // back to source locations. See #17552. - let key = "srcloc"; - let kind = bx.get_md_kind_id(key); + let call = if !labels.is_empty() { + assert!(catch_funclet.is_none()); + bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None) + } else if let Some((catch, funclet)) = catch_funclet { + bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None) + } else { + bx.call(fty, None, None, v, inputs, None, None) + }; - // `srcloc` contains one 64-bit integer for each line of assembly code, - // where the lower 32 bits hold the lo byte position and the upper 32 bits - // hold the hi byte position. - let mut srcloc = vec![]; - if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 { - // LLVM inserts an extra line to add the ".intel_syntax", so add - // a dummy srcloc entry for it. - // - // Don't do this if we only have 1 line span since that may be - // due to the asm template string coming from a macro. LLVM will - // default to the first srcloc for lines that don't have an - // associated srcloc. - srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0))); - } - srcloc.extend(line_spans.iter().map(|span| { - llvm::LLVMValueAsMetadata( - bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)), - ) - })); - let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) }; - let md = bx.get_metadata_value(md); - llvm::LLVMSetMetadata(call, kind, md); + // Store mark in a metadata node so we can map LLVM errors + // back to source locations. See #17552. + let key = "srcloc"; + let kind = bx.get_md_kind_id(key); - Some(call) - } else { - // LLVM has detected an issue with our constraints, bail out - None + // `srcloc` contains one 64-bit integer for each line of assembly code, + // where the lower 32 bits hold the lo byte position and the upper 32 bits + // hold the hi byte position. + let mut srcloc = vec![]; + if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 { + // LLVM inserts an extra line to add the ".intel_syntax", so add + // a dummy srcloc entry for it. + // + // Don't do this if we only have 1 line span since that may be + // due to the asm template string coming from a macro. LLVM will + // default to the first srcloc for lines that don't have an + // associated srcloc. + srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0))); } + srcloc.extend(line_spans.iter().map(|span| { + llvm::LLVMValueAsMetadata( + bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)), + ) + })); + let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) }; + let md = bx.get_metadata_value(md); + llvm::LLVMSetMetadata(call, kind, md); + + Some(call) } /// If the register is an xmm/ymm/zmm register then return its index. diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 4ac77c8f7f1..20721c74608 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1148,9 +1148,9 @@ unsafe fn embed_bitcode( // We need custom section flags, so emit module-level inline assembly. let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); - llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len()); + llvm::append_module_inline_asm(llmod, &asm); let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); - llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len()); + llvm::append_module_inline_asm(llmod, &asm); } } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 04c8118b616..5238755c8eb 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -361,7 +361,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) { + if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) { bundles.push(kcfi_bundle); } @@ -1416,7 +1416,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) { + if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) { bundles.push(kcfi_bundle); } @@ -1749,7 +1749,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) { + if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) { bundles.push(kcfi_bundle); } @@ -1836,7 +1836,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, instance: Option<Instance<'tcx>>, llfn: &'ll Value, - ) -> Option<llvm::OperandBundleOwned<'ll>> { + ) -> Option<llvm::OperandBundleBox<'ll>> { let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) }; let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled() && let Some(fn_abi) = fn_abi @@ -1862,7 +1862,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) }; - Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)])) + Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)])) } else { None }; diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a6f277e4455..3cfa96393e9 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -67,12 +67,12 @@ use crate::value::Value; /// the `OperandBundleDef` value created for MSVC landing pads. pub(crate) struct Funclet<'ll> { cleanuppad: &'ll Value, - operand: llvm::OperandBundleOwned<'ll>, + operand: llvm::OperandBundleBox<'ll>, } impl<'ll> Funclet<'ll> { pub(crate) fn new(cleanuppad: &'ll Value) -> Self { - Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) } + Funclet { cleanuppad, operand: llvm::OperandBundleBox::new("funclet", &[cleanuppad]) } } pub(crate) fn cleanuppad(&self) -> &'ll Value { @@ -80,7 +80,7 @@ impl<'ll> Funclet<'ll> { } pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> { - self.operand.raw() + self.operand.as_ref() } } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index bf81eb648f8..cbac55c7153 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -364,7 +364,12 @@ impl<'ll> CodegenCx<'ll, '_> { if !def_id.is_local() { let needs_dll_storage_attr = self.use_dll_storage_attrs - && !self.tcx.is_foreign_item(def_id) + // If the symbol is a foreign item, then don't automatically apply DLLImport, as + // we'll rely on the #[link] attribute instead. BUT, if this is an internal symbol + // then it may be generated by the compiler in some crate, so we do need to apply + // DLLImport when linking with the MSVC linker. + && (!self.tcx.is_foreign_item(def_id) + || (self.sess().target.is_like_msvc && fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL))) // Local definitions can never be imported, so we must not apply // the DLLImport annotation. && !dso_local diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ed50515b707..b0d8e11d1fb 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1009,11 +1009,27 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64); ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.minimum.f16", fn(t_f16, t_f16) -> t_f16); + ifn!("llvm.minimum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.minimum.f64", fn(t_f64, t_f64) -> t_f64); + // There are issues on x86_64 and aarch64 with the f128 variant. + // - https://github.com/llvm/llvm-project/issues/139380 + // - https://github.com/llvm/llvm-project/issues/139381 + // ifn!("llvm.minimum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16); ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32); ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64); ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.maximum.f16", fn(t_f16, t_f16) -> t_f16); + ifn!("llvm.maximum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.maximum.f64", fn(t_f64, t_f64) -> t_f64); + // There are issues on x86_64 and aarch64 with the f128 variant. + // - https://github.com/llvm/llvm-project/issues/139380 + // - https://github.com/llvm/llvm-project/issues/139381 + // ifn!("llvm.maximum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.floor.f16", fn(t_f16) -> t_f16); ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index bfaad8f2f1e..5ca57375292 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -103,11 +103,23 @@ fn get_simple_intrinsic<'ll>( sym::minnumf64 => "llvm.minnum.f64", sym::minnumf128 => "llvm.minnum.f128", + sym::minimumf16 => "llvm.minimum.f16", + sym::minimumf32 => "llvm.minimum.f32", + sym::minimumf64 => "llvm.minimum.f64", + // There are issues on x86_64 and aarch64 with the f128 variant, + // let's instead use the instrinsic fallback body. + // sym::minimumf128 => "llvm.minimum.f128", sym::maxnumf16 => "llvm.maxnum.f16", sym::maxnumf32 => "llvm.maxnum.f32", sym::maxnumf64 => "llvm.maxnum.f64", sym::maxnumf128 => "llvm.maxnum.f128", + sym::maximumf16 => "llvm.maximum.f16", + sym::maximumf32 => "llvm.maximum.f32", + sym::maximumf64 => "llvm.maximum.f64", + // There are issues on x86_64 and aarch64 with the f128 variant, + // let's instead use the instrinsic fallback body. + // sym::maximumf128 => "llvm.maximum.f128", sym::copysignf16 => "llvm.copysign.f16", sym::copysignf32 => "llvm.copysign.f32", sym::copysignf64 => "llvm.copysign.f64", diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e8010ec9fc4..5736314b96a 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ffb490dcdc2..67a66e6ec79 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,7 +1,7 @@ //! Bindings to the LLVM-C API (`LLVM*`), and to our own `extern "C"` wrapper //! functions around the unstable LLVM C++ API (`LLVMRust*`). //! -//! ## Passing pointer/length strings as `*const c_uchar` +//! ## Passing pointer/length strings as `*const c_uchar` (PTR_LEN_STR) //! //! Normally it's a good idea for Rust-side bindings to match the corresponding //! C-side function declarations as closely as possible. But when passing `&str` @@ -415,6 +415,7 @@ impl AtomicRmwBinOp { pub(crate) enum AtomicOrdering { #[allow(dead_code)] NotAtomic = 0, + #[allow(dead_code)] Unordered = 1, Monotonic = 2, // Consume = 3, // Not specified yet. @@ -428,7 +429,6 @@ impl AtomicOrdering { pub(crate) fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self { use rustc_codegen_ssa::common::AtomicOrdering as Common; match ao { - Common::Unordered => Self::Unordered, Common::Relaxed => Self::Monotonic, Common::Acquire => Self::Acquire, Common::Release => Self::Release, @@ -471,7 +471,7 @@ pub(crate) enum MetadataType { MD_kcfi_type = 36, } -/// LLVMRustAsmDialect +/// Must match the layout of `LLVMInlineAsmDialect`. #[derive(Copy, Clone, PartialEq)] #[repr(C)] pub(crate) enum AsmDialect { @@ -1014,8 +1014,25 @@ unsafe extern "C" { pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char; pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); - /// See Module::setModuleInlineAsm. - pub(crate) fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t); + /// Append inline assembly to a module. See `Module::appendModuleInlineAsm`. + pub(crate) fn LLVMAppendModuleInlineAsm( + M: &Module, + Asm: *const c_uchar, // See "PTR_LEN_STR". + Len: size_t, + ); + + /// Create the specified uniqued inline asm string. See `InlineAsm::get()`. + pub(crate) fn LLVMGetInlineAsm<'ll>( + Ty: &'ll Type, + AsmString: *const c_uchar, // See "PTR_LEN_STR". + AsmStringSize: size_t, + Constraints: *const c_uchar, // See "PTR_LEN_STR". + ConstraintsSize: size_t, + HasSideEffects: llvm::Bool, + IsAlignStack: llvm::Bool, + Dialect: AsmDialect, + CanThrow: llvm::Bool, + ) -> &'ll Value; // Operations on integer types pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type; @@ -1766,7 +1783,7 @@ unsafe extern "C" { pub(crate) fn LLVMDIBuilderCreateNameSpace<'ll>( Builder: &DIBuilder<'ll>, ParentScope: Option<&'ll Metadata>, - Name: *const c_uchar, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, ExportSymbols: llvm::Bool, ) -> &'ll Metadata; @@ -1994,21 +2011,9 @@ unsafe extern "C" { /// Prints the statistics collected by `-Zprint-codegen-stats`. pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString); - /// Prepares inline assembly. - pub(crate) fn LLVMRustInlineAsm( - Ty: &Type, - AsmString: *const c_char, - AsmStringLen: size_t, - Constraints: *const c_char, - ConstraintsLen: size_t, - SideEffects: Bool, - AlignStack: Bool, - Dialect: AsmDialect, - CanThrow: Bool, - ) -> &Value; pub(crate) fn LLVMRustInlineAsmVerify( Ty: &Type, - Constraints: *const c_char, + Constraints: *const c_uchar, // See "PTR_LEN_STR". ConstraintsLen: size_t, ) -> bool; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index d14aab06073..ed23f911930 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -363,12 +363,13 @@ pub(crate) fn last_error() -> Option<String> { } } -/// Owns an [`OperandBundle`], and will dispose of it when dropped. -pub(crate) struct OperandBundleOwned<'a> { +/// Owning pointer to an [`OperandBundle`] that will dispose of the bundle +/// when dropped. +pub(crate) struct OperandBundleBox<'a> { raw: ptr::NonNull<OperandBundle<'a>>, } -impl<'a> OperandBundleOwned<'a> { +impl<'a> OperandBundleBox<'a> { pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self { let raw = unsafe { LLVMCreateOperandBundle( @@ -378,21 +379,21 @@ impl<'a> OperandBundleOwned<'a> { vals.len() as c_uint, ) }; - OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() } + Self { raw: ptr::NonNull::new(raw).unwrap() } } - /// Returns inner `OperandBundle` type. + /// Dereferences to the underlying `&OperandBundle`. /// - /// This could be a `Deref` implementation, but `OperandBundle` contains an extern type and - /// `Deref::Target: ?Sized`. - pub(crate) fn raw(&self) -> &OperandBundle<'a> { + /// This can't be a `Deref` implementation because `OperandBundle` transitively + /// contains an extern type, which is incompatible with `Deref::Target: ?Sized`. + pub(crate) fn as_ref(&self) -> &OperandBundle<'a> { // SAFETY: The returned reference is opaque and can only used for FFI. // It is valid for as long as `&self` is. unsafe { self.raw.as_ref() } } } -impl Drop for OperandBundleOwned<'_> { +impl Drop for OperandBundleBox<'_> { fn drop(&mut self) { unsafe { LLVMDisposeOperandBundle(self.raw); @@ -440,3 +441,11 @@ pub(crate) fn set_dso_local<'ll>(v: &'ll Value) { LLVMRustSetDSOLocal(v, true); } } + +/// Safe wrapper for `LLVMAppendModuleInlineAsm`, which delegates to +/// `Module::appendModuleInlineAsm`. +pub(crate) fn append_module_inline_asm<'ll>(llmod: &'ll Module, asm: &[u8]) { + unsafe { + LLVMAppendModuleInlineAsm(llmod, asm.as_ptr(), asm.len()); + } +} diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8fc83908efb..80ee8ea2228 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -337,7 +337,12 @@ pub(crate) trait Linker { fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]); + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ); fn subsystem(&mut self, subsystem: &str); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} @@ -770,7 +775,12 @@ impl<'a> Linker for GccLinker<'a> { } } - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility in object files typically takes care of this. if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -799,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { debug!(" _{sym}"); writeln!(f, "_{sym}")?; } @@ -814,11 +824,12 @@ impl<'a> Linker for GccLinker<'a> { // .def file similar to MSVC one but without LIBRARY section // because LD doesn't like when it's empty writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); // Quote the name in case it's reserved by linker in some way // (this accounts for names with dots in particular). - writeln!(f, " \"{symbol}\"")?; + writeln!(f, " \"{symbol}\"{kind_marker}")?; } }; if let Err(error) = res { @@ -831,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "{{")?; if !symbols.is_empty() { writeln!(f, " global:")?; - for sym in symbols { + for (sym, _) in symbols { debug!(" {sym};"); writeln!(f, " {sym};")?; } @@ -1098,7 +1109,12 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility takes care of this typically if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -1116,9 +1132,10 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); - writeln!(f, " {symbol}")?; + writeln!(f, " {symbol}{kind_marker}")?; } }; if let Err(error) = res { @@ -1259,14 +1276,19 @@ impl<'a> Linker for EmLinker<'a> { self.cc_arg("-nodefaultlibs"); } - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { debug!("EXPORTED SYMBOLS:"); self.cc_arg("-s"); let mut arg = OsString::from("EXPORTED_FUNCTIONS="); let encoded = serde_json::to_string( - &symbols.iter().map(|sym| "_".to_owned() + sym).collect::<Vec<_>>(), + &symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(), ) .unwrap(); debug!("{encoded}"); @@ -1428,8 +1450,13 @@ impl<'a> Linker for WasmLd<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { - for sym in symbols { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { + for (sym, _) in symbols { self.link_args(&["--export", sym]); } @@ -1563,7 +1590,7 @@ impl<'a> Linker for L4Bender<'a> { self.cc_arg("-nostdlib"); } - fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { + fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); } @@ -1720,12 +1747,17 @@ impl<'a> Linker for AixLinker<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("list.exp"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; // FIXME: use llvm-nm to generate export list. - for symbol in symbols { + for (symbol, _) in symbols { debug!(" _{symbol}"); writeln!(f, " {symbol}")?; } @@ -1769,9 +1801,12 @@ fn for_each_exported_symbols_include_dep<'tcx>( } } -pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { +pub(crate) fn exported_symbols( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { if let Some(ref exports) = tcx.sess.target.override_export_symbols { - return exports.iter().map(ToString::to_string).collect(); + return exports.iter().map(|name| (name.to_string(), SymbolExportKind::Text)).collect(); } if let CrateType::ProcMacro = crate_type { @@ -1781,7 +1816,10 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St } } -fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { +fn exported_symbols_for_non_proc_macro( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { @@ -1789,17 +1827,18 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - // from any cdylib. The latter doesn't work anyway as we use hidden visibility for // compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning. if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) { - symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate( - tcx, symbol, cnum, + symbols.push(( + symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + info.kind, )); - symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum); + symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, info, cnum); } }); symbols } -fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> { +fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> { // `exported_symbols` will be empty when !should_codegen. if !tcx.sess.opts.output_types.should_codegen() { return Vec::new(); @@ -1809,7 +1848,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> { let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx); - vec![proc_macro_decls_name, metadata_symbol_name] + vec![ + (proc_macro_decls_name, SymbolExportKind::Text), + (metadata_symbol_name, SymbolExportKind::Text), + ] } pub(crate) fn linked_symbols( @@ -1831,7 +1873,9 @@ pub(crate) fn linked_symbols( || info.used { symbols.push(( - symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + symbol_export::linking_symbol_name_for_instance_in_crate( + tcx, symbol, info.kind, cnum, + ), info.kind, )); } @@ -1906,7 +1950,13 @@ impl<'a> Linker for PtxLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + _symbols: &[(String, SymbolExportKind)], + ) { + } fn subsystem(&mut self, _subsystem: &str) {} @@ -1975,10 +2025,15 @@ impl<'a> Linker for LlbcLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { match _crate_type { CrateType::Cdylib => { - for sym in symbols { + for (sym, _) in symbols { self.link_args(&["--export-symbol", sym]); } } @@ -2052,11 +2107,16 @@ impl<'a> Linker for BpfLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { writeln!(f, "{sym}")?; } }; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 5f0a0cf922a..06ba5b4f6a7 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -692,6 +692,7 @@ fn calling_convention_for_symbol<'tcx>( pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, + export_kind: SymbolExportKind, instantiating_crate: CrateNum, ) -> String { let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); @@ -712,8 +713,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( let prefix = match &target.arch[..] { "x86" => Some('_'), "x86_64" => None, - "arm64ec" => Some('#'), - // Only x86/64 use symbol decorations. + // Only functions are decorated for arm64ec. + "arm64ec" if export_kind == SymbolExportKind::Text => Some('#'), + // Only x86/64 and arm64ec use symbol decorations. _ => return undecorated, }; @@ -753,9 +755,10 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>( /// Add it to the symbols list for all kernel functions, so that it is exported in the linked /// object. pub(crate) fn extend_exported_symbols<'tcx>( - symbols: &mut Vec<String>, + symbols: &mut Vec<(String, SymbolExportKind)>, tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, + info: SymbolExportInfo, instantiating_crate: CrateNum, ) { let (conv, _) = calling_convention_for_symbol(tcx, symbol); @@ -767,7 +770,7 @@ pub(crate) fn extend_exported_symbols<'tcx>( let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); // Add the symbol for the kernel descriptor (with .kd suffix) - symbols.push(format!("{undecorated}.kd")); + symbols.push((format!("{undecorated}.kd"), info.kind)); } fn maybe_emutls_symbol_name<'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 775ab9071e7..93cbd4cbb7c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -12,9 +12,9 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; -use rustc_hir::ItemId; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; +use rustc_hir::{ItemId, Target}; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; @@ -1038,21 +1038,35 @@ impl CrateInfo { // by the compiler, but that's ok because all this stuff is unstable anyway. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { - let missing_weak_lang_items: FxIndexSet<Symbol> = info + let add_prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => |name: String, _: SymbolExportKind| format!("_{name}"), + (true, "arm64ec") => { + // Only functions are decorated for arm64ec. + |name: String, export_kind: SymbolExportKind| match export_kind { + SymbolExportKind::Text => format!("#{name}"), + _ => name, + } + } + _ => |name: String, _: SymbolExportKind| name, + }; + let missing_weak_lang_items: FxIndexSet<(Symbol, SymbolExportKind)> = info .used_crates .iter() .flat_map(|&cnum| tcx.missing_lang_items(cnum)) .filter(|l| l.is_weak()) .filter_map(|&l| { let name = l.link_name()?; - lang_items::required(tcx, l).then_some(name) + let export_kind = match l.target() { + Target::Fn => SymbolExportKind::Text, + Target::Static => SymbolExportKind::Data, + _ => bug!( + "Don't know what the export kind is for lang item of kind {:?}", + l.target() + ), + }; + lang_items::required(tcx, l).then_some((name, export_kind)) }) .collect(); - let prefix = match (target.is_like_windows, target.arch.as_ref()) { - (true, "x86") => "_", - (true, "arm64ec") => "#", - _ => "", - }; // This loop only adds new items to values of the hash map, so the order in which we // iterate over the values is not important. @@ -1065,10 +1079,13 @@ impl CrateInfo { .for_each(|(_, linked_symbols)| { let mut symbols = missing_weak_lang_items .iter() - .map(|item| { + .map(|(item, export_kind)| { ( - format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())), - SymbolExportKind::Text, + add_prefix( + mangle_internal_symbol(tcx, item.as_str()), + *export_kind, + ), + *export_kind, ) }) .collect::<Vec<_>>(); @@ -1083,12 +1100,12 @@ impl CrateInfo { // errors. linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { ( - format!( - "{prefix}{}", + add_prefix( mangle_internal_symbol( tcx, - global_fn_name(method.name).as_str() - ) + global_fn_name(method.name).as_str(), + ), + SymbolExportKind::Text, ), SymbolExportKind::Text, ) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 5d09e62f274..835ffb7d4fc 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -387,7 +387,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { [sym::arm, sym::a32 | sym::t32] if !tcx.sess.target.has_thumb_interworking => { - tcx.dcx().emit_err(errors::UnsuportedInstructionSet { + tcx.dcx().emit_err(errors::UnsupportedInstructionSet { span: attr.span(), }); None diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 965bd34ac14..6d0c9d8d066 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -61,7 +61,6 @@ pub enum AtomicRmwBinOp { #[derive(Copy, Clone, Debug)] pub enum AtomicOrdering { - Unordered, Relaxed, Acquire, Release, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index c2064397855..d49aac75d05 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -149,7 +149,7 @@ pub(crate) struct NullOnExport { #[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_instruction_set, code = E0779)] -pub(crate) struct UnsuportedInstructionSet { +pub(crate) struct UnsupportedInstructionSet { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index bfec208c4ae..0e410be5a06 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,7 +2,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -219,7 +218,7 @@ pub struct CrateInfo { pub target_cpu: String, pub target_features: Vec<String>, pub crate_types: Vec<CrateType>, - pub exported_symbols: UnordMap<CrateType, Vec<String>>, + pub exported_symbols: UnordMap<CrateType, Vec<(String, SymbolExportKind)>>, pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>, pub local_crate_name: Symbol, pub compiler_builtins: Option<CrateNum>, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 63025a4574f..b0fcfee2adf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -336,7 +336,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let parse_ordering = |bx: &Bx, s| match s { - "unordered" => Unordered, "relaxed" => Relaxed, "acquire" => Acquire, "release" => Release, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 04a8ed1e0f1..090b2a692cf 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -493,11 +493,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?, sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?, + sym::minimumf16 => self.float_minimum_intrinsic::<Half>(args, dest)?, + sym::minimumf32 => self.float_minimum_intrinsic::<Single>(args, dest)?, + sym::minimumf64 => self.float_minimum_intrinsic::<Double>(args, dest)?, + sym::minimumf128 => self.float_minimum_intrinsic::<Quad>(args, dest)?, + sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?, sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?, sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?, sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?, + sym::maximumf16 => self.float_maximum_intrinsic::<Half>(args, dest)?, + sym::maximumf32 => self.float_maximum_intrinsic::<Single>(args, dest)?, + sym::maximumf64 => self.float_maximum_intrinsic::<Double>(args, dest)?, + sym::maximumf128 => self.float_maximum_intrinsic::<Quad>(args, dest)?, + sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?, sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?, sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?, @@ -830,6 +840,38 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } + fn float_minimum_intrinsic<F>( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = a.minimum(b); + let res = self.adjust_nan(res, &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_maximum_intrinsic<F>( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = a.maximum(b); + let res = self.adjust_nan(res, &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + fn float_copysign_intrinsic<F>( &mut self, args: &[OpTy<'tcx, M::Provenance>], diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 7a0c2543c30..bf7a79dcb20 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 95cfe221d3f..056c476d5e1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -7,7 +7,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(decl_macro)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6f37bad9bb4..f8e19e50778 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -7,7 +7,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d4853d1357f..81d4d59ee04 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,4 +1,3 @@ -use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; @@ -1117,7 +1116,6 @@ enum AddSemicolon { /// of functionality used by `InvocationCollector`. trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { type OutputTy = SmallVec<[Self; 1]>; - type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec; type ItemKind = ItemKind; const KIND: AstFragmentKind; fn to_annotatable(self) -> Annotatable; @@ -1134,7 +1132,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn is_mac_call(&self) -> bool { false } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { unreachable!() } fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> { @@ -1189,7 +1187,7 @@ impl InvocationCollectorNode for P<ast::Item> { fn is_mac_call(&self) -> bool { matches!(self.kind, ItemKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.into_inner(); match node.kind { ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1345,7 +1343,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1386,7 +1384,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1427,7 +1425,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItem fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1465,7 +1463,7 @@ impl InvocationCollectorNode for P<ast::ForeignItem> { fn is_mac_call(&self) -> bool { matches!(self.kind, ForeignItemKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.into_inner(); match node.kind { ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1579,7 +1577,6 @@ impl InvocationCollectorNode for ast::Arm { } impl InvocationCollectorNode for ast::Stmt { - type AttrsTy = ast::AttrVec; const KIND: AstFragmentKind = AstFragmentKind::Stmts; fn to_annotatable(self) -> Annotatable { Annotatable::Stmt(P(self)) @@ -1599,7 +1596,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Let(..) | StmtKind::Empty => false, } } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { // We pull macro invocations (both attributes and fn-like macro calls) out of their // `StmtKind`s and treat them as statement macro invocations, not as items or expressions. let (add_semicolon, mac, attrs) = match self.kind { @@ -1693,7 +1690,7 @@ impl InvocationCollectorNode for P<ast::Ty> { fn is_mac_call(&self) -> bool { matches!(self.kind, ast::TyKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.into_inner(); match node.kind { TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), @@ -1717,7 +1714,7 @@ impl InvocationCollectorNode for P<ast::Pat> { fn is_mac_call(&self) -> bool { matches!(self.kind, PatKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.into_inner(); match node.kind { PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), @@ -1728,7 +1725,6 @@ impl InvocationCollectorNode for P<ast::Pat> { impl InvocationCollectorNode for P<ast::Expr> { type OutputTy = P<ast::Expr>; - type AttrsTy = ast::AttrVec; const KIND: AstFragmentKind = AstFragmentKind::Expr; fn to_annotatable(self) -> Annotatable { Annotatable::Expr(self) @@ -1745,7 +1741,7 @@ impl InvocationCollectorNode for P<ast::Expr> { fn is_mac_call(&self) -> bool { matches!(self.kind, ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1757,7 +1753,6 @@ impl InvocationCollectorNode for P<ast::Expr> { struct OptExprTag; impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> { type OutputTy = Option<P<ast::Expr>>; - type AttrsTy = ast::AttrVec; const KIND: AstFragmentKind = AstFragmentKind::OptExpr; fn to_annotatable(self) -> Annotatable { Annotatable::Expr(self.wrapped) @@ -1772,7 +1767,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> { fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.wrapped.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1794,7 +1789,6 @@ impl DummyAstNode for MethodReceiverTag { } impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> { type OutputTy = Self; - type AttrsTy = ast::AttrVec; const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr; fn descr() -> &'static str { "an expression" @@ -1811,7 +1805,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) { let node = self.wrapped.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 79f838e2e33..cd744977bb3 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(rust_logo)] #![feature(array_windows)] #![feature(associated_type_defaults)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e3e4eefe5e1..809d1630dde 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -96,7 +96,7 @@ declare_features! ( /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), /// Allows the use of `#[cfg(<true/false>)]`. - (accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)), + (accepted, cfg_boolean_literals, "1.88.0", Some(131204)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. (accepted, cfg_doctest, "1.40.0", Some(62210)), /// Enables `#[cfg(panic = "...")]` config key. @@ -301,7 +301,7 @@ declare_features! ( /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. (accepted, move_ref_pattern, "1.49.0", Some(68354)), /// Allows using `#[naked]` on functions. - (accepted, naked_functions, "CURRENT_RUSTC_VERSION", Some(90957)), + (accepted, naked_functions, "1.88.0", Some(90957)), /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]` (accepted, native_link_modifiers, "1.61.0", Some(81490)), /// Allows specifying the bundle link modifier diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 402e18c5d14..687d859df53 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -143,7 +143,7 @@ declare_features! ( (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), Some("removed as it caused some confusion and discussion was inactive for years")), /// Allow anonymous constants from an inline `const` block in pattern position - (removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001), + (removed, inline_const_pat, "1.88.0", Some(76001), Some("removed due to implementation concerns as it requires significant refactorings")), /// Lazily evaluate constants. This allows constants to depend on type parameters. (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a5f89b7a076..8fb10736539 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -206,7 +206,7 @@ declare_features! ( /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind (internal, cfg_emscripten_wasm_eh, "1.86.0", None), /// Allows checking whether or not the backend correctly supports unstable float types. - (internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None), + (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), /// Allows writing custom MIR @@ -316,7 +316,7 @@ declare_features! ( // Unstable `#[target_feature]` directives. (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), - (unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)), + (unstable, apx_target_feature, "1.88.0", Some(139284)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), (unstable, bpf_target_feature, "1.54.0", Some(44839)), @@ -327,7 +327,7 @@ declare_features! ( (unstable, loongarch_target_feature, "1.73.0", Some(44839)), (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), - (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)), + (unstable, movrs_target_feature, "1.88.0", Some(137976)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), @@ -385,7 +385,7 @@ declare_features! ( /// Allows associated type defaults. (unstable, associated_type_defaults, "1.2.0", Some(29661)), /// Allows implementing `AsyncDrop`. - (incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)), + (incomplete, async_drop, "1.88.0", Some(126482)), /// Allows async functions to be called from `dyn Trait`. (incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)), /// Allows `#[track_caller]` on async functions. @@ -395,7 +395,7 @@ declare_features! ( /// Allows `async` trait bound modifier. (unstable, async_trait_bounds, "1.85.0", Some(62290)), /// Allows using Intel AVX10 target features and intrinsics - (unstable, avx10_target_feature, "CURRENT_RUSTC_VERSION", Some(138843)), + (unstable, avx10_target_feature, "1.88.0", Some(138843)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled. @@ -483,11 +483,11 @@ declare_features! ( /// Allows exhaustive pattern matching on types that contain uninhabited types. (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Disallows `extern` without an explicit ABI. - (unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)), + (unstable, explicit_extern_abis, "1.88.0", Some(134986)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `#[export_stable]` which indicates that an item is exportable. - (incomplete, export_stable, "CURRENT_RUSTC_VERSION", Some(139939)), + (incomplete, export_stable, "1.88.0", Some(139939)), /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions /// for functions with varargs. (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), @@ -512,7 +512,7 @@ declare_features! ( /// Allows impls for the Freeze trait. (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. - (unstable, frontmatter, "CURRENT_RUSTC_VERSION", Some(136889)), + (unstable, frontmatter, "1.88.0", Some(136889)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. @@ -575,7 +575,7 @@ declare_features! ( /// Allows `mut ref` and `mut ref mut` identifier patterns. (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on `extern "Rust"` functions. - (unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)), + (unstable, naked_functions_rustic_abi, "1.88.0", Some(138997)), /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows specifying the as-needed link modifier @@ -641,7 +641,7 @@ declare_features! ( /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. - (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), + (unstable, super_let, "1.88.0", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index c96bb48a036..d58c70674f6 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -25,9 +25,6 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf { path.to_path_buf() } else { // `/a/b/c/foo/bar.rs` contains the current macro invocation - #[cfg(bootstrap)] - let mut source_file_path = span.source_file().path(); - #[cfg(not(bootstrap))] let mut source_file_path = span.local_file().unwrap(); // `/a/b/c/foo/` source_file_path.pop(); diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 98b41187f11..f93b9e5af53 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -309,6 +309,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// Used for remapped captured lifetimes in an existential `impl Trait` type node. + OpaqueLifetime(Symbol), /// An anonymous associated type from an RPITIT. The symbol refers to the name of the method /// that defined the type. AnonAssocTy(Symbol), @@ -445,7 +447,8 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option<Symbol> { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => Some(name), Impl | ForeignMod @@ -465,9 +468,8 @@ impl DefPathData { fn hashed_symbol(&self) -> Option<Symbol> { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => { - Some(name) - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) + | OpaqueLifetime(name) => Some(name), Impl | ForeignMod @@ -486,9 +488,8 @@ impl DefPathData { pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { - DefPathDataName::Named(name) - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 18f8c523f9d..8684adee29c 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -50,21 +50,14 @@ fn trait_object_roundtrips() { } fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) { - let unambig = TyKind::TraitObject::<'_, ()>( - &[], - TaggedRef::new( - &const { - Lifetime { - hir_id: HirId::INVALID, - ident: Ident::new(sym::name, DUMMY_SP), - kind: LifetimeKind::Static, - source: LifetimeSource::Other, - syntax: LifetimeSyntax::Hidden, - } - }, - syntax, - ), - ); + let lt = Lifetime { + hir_id: HirId::INVALID, + ident: Ident::new(sym::name, DUMMY_SP), + kind: LifetimeKind::Static, + source: LifetimeSource::Other, + syntax: LifetimeSyntax::Hidden, + }; + let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(<, syntax)); let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) }; match unambig_to_ambig { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 5533920aee4..7a5ff890689 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(closure_track_caller)] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 277bb7bd3e1..f7f2b78f052 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -522,7 +522,7 @@ hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait -hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` +hir_analysis_traits_with_default_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} 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 bbf36fef1dd..fb67f2fd223 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -5,7 +5,7 @@ use std::iter; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; @@ -14,10 +14,10 @@ use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, + TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>( // but found 0" it's confusing, because it looks like there // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. - if trait_params != impl_params { - let span = tcx - .hir_get_generics(impl_m.def_id.expect_local()) - .expect("expected impl item to have generics or else we can't compare them") - .span; - - let mut generics_span = None; - let mut bounds_span = vec![]; - let mut where_span = None; - if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) - && let Some(trait_generics) = trait_node.generics() - { - generics_span = Some(trait_generics.span); - // FIXME: we could potentially look at the impl's bounds to not point at bounds that - // *are* present in the impl. - for p in trait_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + if trait_params == impl_params { + return Ok(()); + } + + if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) { + return Err(guar); + } + + let span = tcx + .hir_get_generics(impl_m.def_id.expect_local()) + .expect("expected impl item to have generics or else we can't compare them") + .span; + + let mut generics_span = None; + let mut bounds_span = vec![]; + let mut where_span = None; + + if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) + && let Some(trait_generics) = trait_node.generics() + { + generics_span = Some(trait_generics.span); + // FIXME: we could potentially look at the impl's bounds to not point at bounds that + // *are* present in the impl. + for p in trait_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(lt) = b { bounds_span.push(lt.ident.span); } } } + _ => {} } - if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) - && let Some(impl_generics) = impl_node.generics() - { - let mut impl_bounds = 0; - for p in impl_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + } + if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) + && let Some(impl_generics) = impl_node.generics() + { + let mut impl_bounds = 0; + for p in impl_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(_) = b { impl_bounds += 1; } } } + _ => {} + } + } + if impl_bounds == bounds_span.len() { + bounds_span = vec![]; + } else if impl_generics.has_where_clause_predicates { + where_span = Some(impl_generics.where_clause_span); + } + } + } + + let reported = tcx + .dcx() + .create_err(LifetimesOrBoundsMismatchOnTrait { + span, + item_kind: impl_m.descr(), + ident: impl_m.ident(tcx), + generics_span, + bounds_span, + where_span, + }) + .emit_unless(delay); + + Err(reported) +} + +#[allow(unused)] +enum LateEarlyMismatch<'tcx> { + EarlyInImpl(DefId, DefId, ty::Region<'tcx>), + LateInImpl(DefId, DefId, ty::Region<'tcx>), +} + +fn check_region_late_boundedness<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: ty::AssocItem, + trait_m: ty::AssocItem, +) -> Option<ErrorGuaranteed> { + if !impl_m.is_fn() { + return None; + } + + let (infcx, param_env) = tcx + .infer_ctxt() + .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id)); + + let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id); + let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args); + let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig); + + let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id); + let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args); + let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig); + + let ocx = ObligationCtxt::new(&infcx); + + // Equate the signatures so that we can infer whether a late-bound param was present where + // an early-bound param was expected, since we replace the late-bound lifetimes with + // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will + // resolve to `ReLateParam` if there is a mismatch. + let Ok(()) = ocx.eq( + &ObligationCause::dummy(), + param_env, + ty::Binder::dummy(trait_m_sig), + ty::Binder::dummy(impl_m_sig), + ) else { + return None; + }; + + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return None; + } + + let mut mismatched = vec![]; + + let impl_generics = tcx.generics_of(impl_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(trait_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::EarlyInImpl( + impl_generics.region_param(ebr, tcx).def_id, + trait_param_def_id, + id_arg.expect_region(), + )); + } + } + + let trait_generics = tcx.generics_of(trait_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(impl_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_generics.region_param(ebr, tcx).def_id, + id_arg.expect_region(), + )); + } + } + + if mismatched.is_empty() { + return None; + } + + let spans: Vec<_> = mismatched + .iter() + .map(|param| { + let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..) + | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param; + tcx.def_span(impl_param_def_id) + }) + .collect(); + + let mut diag = tcx + .dcx() + .struct_span_err(spans, "lifetime parameters do not match the trait definition") + .with_note("lifetime parameters differ in whether they are early- or late-bound") + .with_code(E0195); + for mismatch in mismatched { + match mismatch { + LateEarlyMismatch::EarlyInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, impl_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(impl_param_def_id) + ), + ); } - if impl_bounds == bounds_span.len() { - bounds_span = vec![]; - } else if impl_generics.has_where_clause_predicates { - where_span = Some(impl_generics.where_clause_span); + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); + } + LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, trait_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(trait_param_def_id) + ), + ); } + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); } } - let reported = tcx - .dcx() - .create_err(LifetimesOrBoundsMismatchOnTrait { - span, - item_kind: impl_m.descr(), - ident: impl_m.ident(tcx), - generics_span, - bounds_span, - where_span, - }) - .emit_unless(delay); - return Err(reported); } - Ok(()) + Some(diag.emit()) +} + +fn find_region_in_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + early_bound_region: ty::Region<'tcx>, +) -> Option<Span> { + for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) { + if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() { + return Some(span); + } + } + + struct FindRegion<'tcx>(ty::Region<'tcx>); + impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> { + type Result = ControlFlow<()>; + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } + } + } + + None } #[instrument(level = "debug", skip(infcx))] diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 692784bf171..9fd158ad154 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -103,10 +103,18 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::minnumf32 | sym::minnumf64 | sym::minnumf128 + | sym::minimumf16 + | sym::minimumf32 + | sym::minimumf64 + | sym::minimumf128 | sym::maxnumf16 | sym::maxnumf32 | sym::maxnumf64 | sym::maxnumf128 + | sym::maximumf16 + | sym::maximumf32 + | sym::maximumf64 + | sym::maximumf128 | sym::rustc_peek | sym::type_name | sym::forget @@ -374,11 +382,21 @@ pub(crate) fn check_intrinsic_type( sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::minimumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), + sym::minimumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::minimumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::minimumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::maximumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), + sym::maximumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::maximumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::maximumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index a89160785eb..709446d09cd 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -14,7 +14,7 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DisambiguatorState; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{ self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node, @@ -1470,14 +1470,14 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let mut captures = captures.borrow_mut(); let remapped = *captures.entry(lifetime).or_insert_with(|| { // `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once - // per `resolve_bound_vars` query. This is the only location that creates nested - // lifetime inside a opaque type. `<opaque_def_id>::LifetimeNs(..)` is thus unique + // per `resolve_bound_vars` query. This is the only location that creates + // `OpaqueLifetime` paths. `<opaque_def_id>::OpaqueLifetime(..)` is thus unique // to this query and duplicates within the query are handled by `self.disambiguator`. let feed = self.tcx.create_def( opaque_def_id, - Some(ident.name), - DefKind::LifetimeParam, None, + DefKind::LifetimeParam, + Some(DefPathData::OpaqueLifetime(ident.name)), &mut self.disambiguator, ); feed.def_span(ident.span); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2b1661aaac8..152714b3407 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1327,7 +1327,7 @@ pub(crate) struct ImplForTyRequires { } #[derive(Diagnostic)] -#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)] +#[diag(hir_analysis_traits_with_default_impl, code = E0321)] #[note] pub(crate) struct TraitsWithDefaultImpl<'a> { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index bf91eb1b8fd..4419d5dc7d6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{AmbigArg, HirId}; use rustc_middle::bug; use rustc_middle::ty::{ - self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; @@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> { type Result = ControlFlow<ErrorGuaranteed>; - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, binder: &ty::Binder<'tcx, T>, ) -> Self::Result { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 88f74589204..f6e5149bd2b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -172,7 +172,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = vec![]; + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: <https://github.com/rust-lang/rust/pull/136458>. + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { let principal_trait = principal_trait.map_bound(|trait_pred| { assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); @@ -197,16 +204,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); - needed_associated_types.extend( + ordered_associated_types.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. .filter(|item| item.is_type()) // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(|item| (item.def_id, trait_ref)), ); } @@ -278,14 +282,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. let mut missing_assoc_types = FxIndexSet::default(); - let projection_bounds: Vec<_> = needed_associated_types + let projection_bounds: Vec<_> = ordered_associated_types .into_iter() .filter_map(|key| { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - missing_assoc_types.insert(key); + // If the associated type has a `where Self: Sized` bound, then + // we do not need to provide the associated type. This results in + // a `dyn Trait` type that has a different number of projection + // bounds, which may lead to type mismatches. + if !tcx.generics_require_sized_self(key.0) { + missing_assoc_types.insert(key); + } None } }) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 91dde13be55..4937eb73a8b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -59,7 +59,6 @@ This API is completely unstable and subject to change. #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -223,10 +222,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } _ => (), } - }); - - tcx.par_hir_body_owners(|item_def_id| { - let def_kind = tcx.def_kind(item_def_id); // Skip `AnonConst`s because we feed their `type_of`. if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 09bf84ab64f..04f9c831b0a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,7 +2,6 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] #![recursion_limit = "256"] // tidy-alphabetical-end diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6cc7e82bbf7..d2cdfe22a3a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2339,7 +2339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !mismatched_params.is_empty() { - // For each mismatched paramter, create a two-way link to each matched parameter + // For each mismatched parameter, create a two-way link to each matched parameter // of the same type. let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n( |_| SmallVec::<[u32; 4]>::new(), diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 78233a34c46..161f5e981d4 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] @@ -32,6 +31,7 @@ mod gather_locals; mod intrinsicck; mod method; mod op; +mod opaque_types; mod pat; mod place_op; mod rvalue_scopes; @@ -245,9 +245,7 @@ fn typeck_with_inspect<'tcx>( let typeck_results = fcx.resolve_type_vars_in_body(body); - // We clone the defined opaque types during writeback in the new solver - // because we have to use them during normalization. - let _ = fcx.infcx.take_opaque_types(); + fcx.detect_opaque_types_added_during_writeback(); // Consistency check our TypeckResults instance can hold all ItemLocalIds // it will need to hold. diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs new file mode 100644 index 00000000000..e0224f8c6e1 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -0,0 +1,26 @@ +use super::FnCtxt; +impl<'tcx> FnCtxt<'_, 'tcx> { + /// We may in theory add further uses of an opaque after cloning the opaque + /// types storage during writeback when computing the defining uses. + /// + /// Silently ignoring them is dangerous and could result in ICE or even in + /// unsoundness, so we make sure we catch such cases here. There's currently + /// no known code where this actually happens, even with the new solver which + /// does normalize types in writeback after cloning the opaque type storage. + /// + /// FIXME(@lcnr): I believe this should be possible in theory and would like + /// an actual test here. After playing around with this for an hour, I wasn't + /// able to do anything which didn't already try to normalize the opaque before + /// then, either allowing compilation to succeed or causing an ambiguity error. + pub(super) fn detect_opaque_types_added_during_writeback(&self) { + let num_entries = self.checked_opaque_types_storage_entries.take().unwrap(); + for (key, hidden_type) in + self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries) + { + let opaque_type_string = self.tcx.def_path_str(key.def_id); + let msg = format!("unexpected cyclic definition of `{opaque_type_string}`"); + self.dcx().span_delayed_bug(hidden_type.span, msg); + } + let _ = self.take_opaque_types(); + } +} diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f9502153afd..17d48184dd9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -650,14 +650,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. - PatKind::Tuple(..) - | PatKind::Range(..) - | PatKind::Slice(..) => AdjustMode::peel_all(), + PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(), // When checking an explicit deref pattern, only peel reference types. // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box // patterns may want `PeelKind::Implicit`, stopping on encountering a box. - | PatKind::Box(_) - | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }, + PatKind::Box(_) | PatKind::Deref(_) => { + AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat } + } // A never pattern behaves somewhat like a literal or unit variant. PatKind::Never => AdjustMode::peel_all(), // For patterns with paths, how we peel the scrutinee depends on the path's resolution. @@ -679,7 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.tcx.features().deref_patterns() && !matches!(lt.kind, PatExprKind::Lit { .. }) { - span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind); + span_bug!( + lt.span, + "FIXME(deref_patterns): adjust mode unimplemented for {:?}", + lt.kind + ); } // Call `resolve_vars_if_possible` here for inline const blocks. let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)); @@ -687,17 +690,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.features().deref_patterns() { let mut peeled_ty = lit_ty; let mut pat_ref_layers = 0; - while let ty::Ref(_, inner_ty, mutbl) = *peeled_ty.kind() { + while let ty::Ref(_, inner_ty, mutbl) = + *self.try_structurally_resolve_type(pat.span, peeled_ty).kind() + { // We rely on references at the head of constants being immutable. debug_assert!(mutbl.is_not()); pat_ref_layers += 1; peeled_ty = inner_ty; } - AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: None, pat_ref_layers } } + AdjustMode::Peel { + kind: PeelKind::Implicit { until_adt: None, pat_ref_layers }, + } } else { if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() } } - }, + } // Ref patterns are complicated, we handle them in `check_pat_ref`. PatKind::Ref(..) @@ -928,6 +935,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be peeled to `str` while ty here is still `&str`, if we don't // err early here, a rather confusing unification error will be // emitted instead). + let ty = self.try_structurally_resolve_type(expr.span, ty); let fail = !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); Some((fail, ty, expr.span)) diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 56859eef45f..26be5fc6d19 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -1,10 +1,10 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::Deref; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, HirId, HirIdMap, LangItem}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt}; use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::Span; @@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>, + // Used to detect opaque types uses added after we've already checked them. + // + // See [FnCtxt::detect_opaque_types_added_during_writeback] for more details. + pub(super) checked_opaque_types_storage_entries: Cell<Option<OpaqueTypeStorageEntries>>, + /// Some additional `Sized` obligations badly affect type inference. /// These obligations are added in a later stage of typeck. /// Removing these may also cause additional complications, see #101066. @@ -85,12 +90,14 @@ impl<'tcx> TypeckRootCtxt<'tcx> { let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); + let fulfillment_cx = RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)); TypeckRootCtxt { - typeck_results, - fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)), infcx, + typeck_results, locals: RefCell::new(Default::default()), + fulfillment_cx, + checked_opaque_types_storage_entries: Cell::new(None), deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8e7ce83044c..9be041f75d7 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -535,13 +535,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let tcx = self.tcx(); // We clone the opaques instead of stealing them here as they are still used for // normalization in the next generation trait solver. - // - // FIXME(-Znext-solver): Opaque types defined after this would simply get dropped - // at the end of typeck. While this seems unlikely to happen in practice this - // should still get fixed. Either by preventing writeback from defining new opaque - // types or by using this function at the end of writeback and running it as a - // fixpoint. let opaque_types = self.fcx.infcx.clone_opaque_types(); + let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries(); + let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries)); + debug_assert_eq!(prev, None); for (opaque_type_key, hidden_type) in opaque_types { let hidden_type = self.resolve(hidden_type, &hidden_type.span); let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span); diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 22d7ce79bb4..359b9da11ce 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -6,7 +6,10 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; -use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; +use super::{ + BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin, + SubregionOrigin, +}; impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; @@ -213,4 +216,58 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); } + + type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; + fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries { + self.inner.borrow_mut().opaque_types().num_entries() + } + fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect() + } + fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .iter_duplicate_entries() + .map(|(k, h)| (k, h.ty)) + .collect() + } + fn clone_opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .opaque_types_added_since(prev_entries) + .map(|(k, h)| (k, h.ty)) + .collect() + } + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) -> Option<Ty<'tcx>> { + self.register_hidden_type_in_storage( + opaque_type_key, + ty::OpaqueHiddenType { span, ty: hidden_ty }, + ) + } + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) { + self.inner + .borrow_mut() + .opaque_types() + .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty }) + } + + fn reset_opaque_types(&self) { + let _ = self.take_opaque_types(); + } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 070d285b5a6..b408d76010d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,7 +9,7 @@ use free_regions::RegionRelations; pub use freshen::TypeFreshener; use lexical_region_resolve::LexicalRegionResolutions; pub use lexical_region_resolve::RegionResolutionError; -use opaque_types::OpaqueTypeStorage; +pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; use region_constraints::{ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound, }; diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index df7144c31da..220d5e9bda2 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -18,7 +18,7 @@ use crate::traits::{self, Obligation, PredicateObligations}; mod table; -pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable}; +pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; impl<'tcx> InferCtxt<'tcx> { /// This is a backwards compatibility hack to prevent breaking changes from diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 3c5bf9d722b..46752840e1b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -14,6 +14,16 @@ pub struct OpaqueTypeStorage<'tcx> { duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>, } +/// The number of entries in the opaque type storage at a given point. +/// +/// Used to check that we haven't added any new opaque types after checking +/// the opaque types currently in the storage. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub struct OpaqueTypeStorageEntries { + opaque_types: usize, + duplicate_entries: usize, +} + impl<'tcx> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] pub(crate) fn remove( @@ -49,6 +59,24 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries)) } + pub fn num_entries(&self) -> OpaqueTypeStorageEntries { + OpaqueTypeStorageEntries { + opaque_types: self.opaque_types.len(), + duplicate_entries: self.duplicate_entries.len(), + } + } + + pub fn opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> { + self.opaque_types + .iter() + .skip(prev_entries.opaque_types) + .map(|(k, v)| (*k, *v)) + .chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied()) + } + /// Only returns the opaque types from the lookup table. These are used /// when normalizing opaque types and have a unique key. /// diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index c44d9723f29..2a4b9776f68 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -24,10 +24,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 8b2aab42042..ab7b7060c09 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,7 +16,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 41280707183..ce2398fab91 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(decl_macro)] #![feature(file_buffered)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f4d11a7c0be..7ed32d559c3 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -907,7 +907,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>( feed.output_filenames(Arc::new(outputs)); let res = f(tcx); - // FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()? + // FIXME maybe run finish even when a fatal error occurred? or at least tcx.alloc_self_profile_query_strings()? tcx.finish(); res }, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0ceda220134..068d96c860f 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -720,7 +720,7 @@ fn test_unstable_options_tracking_hash() { untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); untracked!(print_llvm_passes, true); - untracked!(print_mono_items, Some(String::from("abc"))); + untracked!(print_mono_items, true); untracked!(print_type_sizes, true); untracked!(proc_macro_backtrace, true); untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread); diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 757fc1f58bd..a56b753bda7 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -49,6 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let Some((pat, arg)) = extract_for_loop(expr) else { return }; + let arg_span = arg.span.source_callsite(); + let ty = cx.typeck_results().expr_ty(arg); let (adt, args, ref_mutability) = match ty.kind() { @@ -78,27 +80,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { ForLoopsOverFalliblesLoopSub::RemoveNext { - suggestion: recv.span.between(arg.span.shrink_to_hi()), + suggestion: recv.span.between(arg_span.shrink_to_hi()), recv_snip, } } else { ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), var, } }; let question_mark = suggest_question_mark(cx, adt, args, expr.span) - .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() }); + .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg_span.shrink_to_hi() }); let suggestion = ForLoopsOverFalliblesSuggestion { var, start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), }; cx.emit_span_lint( FOR_LOOPS_OVER_FALLIBLES, - arg.span, + arg_span, ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion }, ); } diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 7f4789ad0d9..a8f45d043be 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -15,7 +15,8 @@ use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; @@ -209,7 +210,7 @@ where VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>, OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>, { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b910d6a138e..4ff586a79a6 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -21,7 +21,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 72369ab7b69..90aa9188c83 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -622,37 +622,10 @@ extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B, return wrap(SI); } -enum class LLVMRustAsmDialect { - Att, - Intel, -}; - -static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) { - switch (Dialect) { - case LLVMRustAsmDialect::Att: - return InlineAsm::AD_ATT; - case LLVMRustAsmDialect::Intel: - return InlineAsm::AD_Intel; - default: - report_fatal_error("bad AsmDialect."); - } -} - extern "C" uint64_t LLVMRustGetArrayNumElements(LLVMTypeRef Ty) { return unwrap(Ty)->getArrayNumElements(); } -extern "C" LLVMValueRef -LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, - char *Constraints, size_t ConstraintsLen, - LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMRustAsmDialect Dialect, LLVMBool CanThrow) { - return wrap(InlineAsm::get( - unwrap<FunctionType>(Ty), StringRef(AsmString, AsmStringLen), - StringRef(Constraints, ConstraintsLen), HasSideEffects, IsAlignStack, - fromRust(Dialect), CanThrow)); -} - extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, size_t ConstraintsLen) { // llvm::Error converts to true if it is an error. diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 62ca7ce3ca9..81817018cb1 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(rustc::default_hash_types)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(if_let_guard)] #![feature(never_type)] #![feature(proc_macro_diagnostic)] diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 0400de62274..2b00b7dd27a 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -299,7 +299,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) { let output = quote! { const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base; - /// The number of predefined symbols; this is the the first index for + /// The number of predefined symbols; this is the first index for /// extra pre-interned symbols in an Interner created via /// [`Interner::with_extra_symbols`]. pub const PREDEFINED_SYMBOLS_COUNT: u32 = #predefined_symbols_count; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 3931be1654a..97b67140fa2 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(coroutines)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 979608df79c..cb3fdd4d3f7 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,7 +28,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 1d67d0fe3bb..64a1f2aff15 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -22,7 +22,7 @@ impl SymbolExportLevel { } /// Kind of exported symbols. -#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable, Hash)] pub enum SymbolExportKind { Text, Data, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2d69a1c2b55..dda0faa3afe 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1924,6 +1924,9 @@ impl<'tcx> TyCtxt<'tcx> { def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Option<&'tcx CoroutineLayout<'tcx>> { + if args[0].has_placeholders() || args[0].has_non_region_param() { + return None; + } let instance = InstanceKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args)); self.mir_shims(instance).coroutine_layout_raw() } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bc1423a9e3c..0250c777faf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2934,7 +2934,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>) where - T: TypeVisitable<TyCtxt<'tcx>>, + T: TypeFoldable<TyCtxt<'tcx>>, { struct RegionNameCollector<'tcx> { used_region_names: FxHashSet<Symbol>, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2165cf186bd..c31ce1bc630 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -723,7 +723,10 @@ impl<'tcx> Ty<'tcx> { repr: DynKind, ) -> Ty<'tcx> { if cfg!(debug_assertions) { - let projection_count = obj.projection_bounds().count(); + let projection_count = obj + .projection_bounds() + .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) + .count(); let expected_count: usize = obj .principal_def_id() .into_iter() diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 3853a804a92..f8042174599 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -66,7 +66,7 @@ impl<'tcx> TyCtxt<'tcx> { { type Result = ControlFlow<()>; - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, t: &Binder<'tcx, T>, ) -> Self::Result { @@ -168,7 +168,7 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) { + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); t.super_visit_with(self); self.current_index.shift_out(1); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 7c287129820..2a30777e98c 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// panic occurred (a subset of the drops in `scope`, since we sometimes elide StorageDead and other /// instructions on unwinding) /// * `dropline_to`, describes the drops that would occur at this point in the code if a -/// coroutine drop occured. +/// coroutine drop occurred. /// * `storage_dead_on_unwind`, if true, then we should emit `StorageDead` even when unwinding /// * `arg_count`, number of MIR local variables corresponding to fn arguments (used to assert that we don't drop those) fn build_scope_drops<'tcx, F>( diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a051cf570b7..8c7003b7787 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 658fbf505e4..2e8c9165441 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs index 4aff127908e..8da17a056e3 100644 --- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs +++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs @@ -55,18 +55,45 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { }, // char → u32 (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")), + // char (→ u32) → i32 + (Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")), // u32 → char (Uint(UintTy::U32), Char) => Error { sugg: format!("char::from_u32_unchecked({arg})"), help: Some("consider `char::from_u32(…).unwrap()`"), span, }, + // i32 → char + (Int(IntTy::I32), Char) => Error { + sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"), + help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"), + span, + }, // uNN → iNN (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())), // iNN → uNN (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())), + // fNN → xsize + (Float(ty), Uint(UintTy::Usize)) => { + err(format!("{}::to_bits({arg}) as usize", ty.name_str())) + } + (Float(ty), Int(IntTy::Isize)) => { + err(format!("{}::to_bits({arg}) as isize", ty.name_str())) + } + // fNN (→ uNN) → iNN + (Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())), // fNN → uNN (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())), + // xsize → fNN + (Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => { + err(format!("{}::from_bits({arg} as _)", ty.name_str(),)) + } + // iNN (→ uNN) → fNN + (Int(int_ty), Float(ty)) => err(format!( + "{}::from_bits({}::cast_unsigned({arg}))", + ty.name_str(), + int_ty.name_str() + )), // uNN → fNN (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())), // bool → { x8 } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index dc0eacd3613..10dbb3437dc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(array_windows)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 6b6653e7de0..35bedf4318f 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -60,9 +60,6 @@ monomorphize_start_not_found = using `fn main` requires the standard library monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined -monomorphize_unknown_cgu_collection_mode = - unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode - monomorphize_wasm_c_abi_transition = this function {$is_call -> [true] call diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 0dd20bbb35f..acf77b5916e 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -65,12 +65,6 @@ pub(crate) struct EncounteredErrorWhileInstantiating { pub(crate) struct StartNotFound; #[derive(Diagnostic)] -#[diag(monomorphize_unknown_cgu_collection_mode)] -pub(crate) struct UnknownCguCollectionMode<'a> { - pub mode: &'a str, -} - -#[derive(Diagnostic)] #[diag(monomorphize_abi_error_disabled_vector_type)] #[help] pub(crate) struct AbiErrorDisabledVectorType<'a> { diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 1b484da698a..5c66017bc61 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(array_windows)] #![feature(file_buffered)] #![feature(if_let_guard)] diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 6948dceddf9..c3a41529794 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -124,7 +124,7 @@ use rustc_target::spec::SymbolVisibility; use tracing::debug; use crate::collector::{self, MonoItemCollectionStrategy, UsageMap}; -use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode}; +use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined}; struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -1127,27 +1127,10 @@ where } fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitions<'_> { - let collection_strategy = match tcx.sess.opts.unstable_opts.print_mono_items { - Some(ref s) => { - let mode = s.to_lowercase(); - let mode = mode.trim(); - if mode == "eager" { - MonoItemCollectionStrategy::Eager - } else { - if mode != "lazy" { - tcx.dcx().emit_warn(UnknownCguCollectionMode { mode }); - } - - MonoItemCollectionStrategy::Lazy - } - } - None => { - if tcx.sess.link_dead_code() { - MonoItemCollectionStrategy::Eager - } else { - MonoItemCollectionStrategy::Lazy - } - } + let collection_strategy = if tcx.sess.link_dead_code() { + MonoItemCollectionStrategy::Eager + } else { + MonoItemCollectionStrategy::Lazy }; let (items, usage_map) = collector::collect_crate_mono_items(tcx, collection_strategy); @@ -1209,7 +1192,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio } } - if tcx.sess.opts.unstable_opts.print_mono_items.is_some() { + if tcx.sess.opts.unstable_opts.print_mono_items { let mut item_to_cgus: UnordMap<_, Vec<_>> = Default::default(); for cgu in codegen_units { diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 9e8fbd66b70..90a7c2e9f78 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -39,13 +39,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { term: <Self::Interner as Interner>::Term, ) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>; - fn clone_opaque_types_lookup_table( - &self, - ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>; - fn clone_duplicate_opaque_types( - &self, - ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>; - fn make_deduplicated_outlives_constraints( &self, ) -> Vec<ty::OutlivesPredicate<Self::Interner, <Self::Interner as Interner>::GenericArg>>; @@ -64,20 +57,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { span: <Self::Interner as Interner>::Span, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> <Self::Interner as Interner>::GenericArg; - - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey<Self::Interner>, - hidden_ty: <Self::Interner as Interner>::Ty, - span: <Self::Interner as Interner>::Span, - ) -> Option<<Self::Interner as Interner>::Ty>; - fn add_duplicate_opaque_type( - &self, - opaque_type_key: ty::OpaqueTypeKey<Self::Interner>, - hidden_ty: <Self::Interner as Interner>::Ty, - span: <Self::Interner as Interner>::Span, - ); - fn add_item_bounds_for_hidden_type( &self, def_id: <Self::Interner as Interner>::DefId, @@ -86,7 +65,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { hidden_ty: <Self::Interner as Interner>::Ty, goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, ); - fn reset_opaque_types(&self); fn fetch_eligible_assoc_item( &self, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 101129a231e..345a272895d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -2,21 +2,24 @@ pub(super) mod structural_traits; +use std::ops::ControlFlow; + use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::{ - self as ty, Interner, TypeFoldable, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, + self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, + TypeVisitor, TypingMode, Upcast as _, elaborate, }; use tracing::{debug, instrument}; -use super::has_only_region_constraints; use super::trait_goals::TraitGoalProvenVia; +use super::{has_only_region_constraints, inspect}; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, - MaybeCause, NoSolution, QueryResult, + MaybeCause, NoSolution, ParamEnvSource, QueryResult, }; enum AliasBoundKind { @@ -49,18 +52,6 @@ where fn trait_def_id(self, cx: I) -> I::DefId; - /// Try equating an assumption predicate against a goal's predicate. If it - /// holds, then execute the `then` callback, which should do any additional - /// work, then produce a response (typically by executing - /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). - fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource<I>, - goal: Goal<I, Self>, - assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, - ) -> Result<Candidate<I>, NoSolution>; - /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. @@ -119,6 +110,67 @@ where alias_ty: ty::AliasTy<I>, ) -> Vec<Candidate<I>>; + fn probe_and_consider_param_env_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<Candidate<I>, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe(|candidate: &Result<Candidate<I>, NoSolution>| match candidate { + Ok(candidate) => inspect::ProbeKind::TraitCandidate { + source: candidate.source, + result: Ok(candidate.result), + }, + Err(NoSolution) => inspect::ProbeKind::TraitCandidate { + source: CandidateSource::ParamEnv(ParamEnvSource::Global), + result: Err(NoSolution), + }, + }) + .enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + let source = ecx.characterize_param_env_assumption(goal.param_env, assumption)?; + Ok(Candidate { + source, + result: ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?, + }) + }) + } + + /// Try equating an assumption predicate against a goal's predicate. If it + /// holds, then execute the `then` callback, which should do any additional + /// work, then produce a response (typically by executing + /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). + fn probe_and_match_goal_against_assumption( + ecx: &mut EvalCtxt<'_, D>, + source: CandidateSource<I>, + goal: Goal<I, Self>, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, + ) -> Result<Candidate<I>, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe_trait_candidate(source).enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + then(ecx) + }) + } + + /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] + /// and `DefId`. + fn fast_reject_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + + /// Relate the goal and assumption. + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, @@ -500,14 +552,8 @@ where goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, ) { - for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - candidates.extend(G::probe_and_consider_implied_clause( - self, - CandidateSource::ParamEnv(i), - goal, - assumption, - [], - )); + for assumption in goal.param_env.caller_bounds().iter() { + candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption)); } } @@ -943,4 +989,88 @@ where } } } + + /// Compute whether a param-env assumption is global or non-global after normalizing it. + /// + /// This is necessary because, for example, given: + /// + /// ```ignore,rust + /// where + /// T: Trait<Assoc = u32>, + /// i32: From<T::Assoc>, + /// ``` + /// + /// The `i32: From<T::Assoc>` bound is non-global before normalization, but is global after. + /// Since the old trait solver normalized param-envs eagerly, we want to emulate this + /// behavior lazily. + fn characterize_param_env_assumption( + &mut self, + param_env: I::ParamEnv, + assumption: I::Clause, + ) -> Result<CandidateSource<I>, NoSolution> { + // FIXME: This should be fixed, but it also requires changing the behavior + // in the old solver which is currently relied on. + if assumption.has_bound_vars() { + return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)); + } + + match assumption.visit_with(&mut FindParamInClause { ecx: self, param_env }) { + ControlFlow::Break(Err(NoSolution)) => Err(NoSolution), + ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)), + ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)), + } + } +} + +struct FindParamInClause<'a, 'b, D: SolverDelegate<Interner = I>, I: Interner> { + ecx: &'a mut EvalCtxt<'b, D>, + param_env: I::ParamEnv, +} + +impl<D, I> TypeVisitor<I> for FindParamInClause<'_, '_, D, I> +where + D: SolverDelegate<Interner = I>, + I: Interner, +{ + type Result = ControlFlow<Result<(), NoSolution>>; + + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { + self.ecx.enter_forall(t.clone(), |ecx, v| { + v.visit_with(&mut FindParamInClause { ecx, param_env: self.param_env }) + }) + } + + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::Placeholder(_) = ty.kind() { + ControlFlow::Break(Ok(())) + } else { + ty.super_visit_with(self) + } + } + + fn visit_const(&mut self, ct: I::Const) -> Self::Result { + let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::ConstKind::Placeholder(_) = ct.kind() { + ControlFlow::Break(Ok(())) + } else { + ct.super_visit_with(self) + } + } + + fn visit_region(&mut self, r: I::Region) -> Self::Result { + match self.ecx.eager_resolve_region(r).kind() { + ty::ReStatic | ty::ReError(_) => ControlFlow::Continue(()), + ty::ReVar(_) | ty::RePlaceholder(_) => ControlFlow::Break(Ok(())), + ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReBound(..) => { + unreachable!() + } + } + } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index b16f74cd8e4..2a2b462a36c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -945,7 +945,7 @@ where // This is quite similar to the `projection_may_match` we use in unsizing, // but here we want to unify a projection predicate against an alias term - // so we can replace it with the the projection predicate's term. + // so we can replace it with the projection predicate's term. let mut matching_projections = replacements .iter() .filter(|source_projection| self.projection_may_match(**source_projection, alias_term)); diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 5edc777262b..84a83d79cf0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -36,39 +36,38 @@ where self.def_id() } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: rustc_type_ir::solve::CandidateSource<I>, goal: Goal<I, Self>, - assumption: <I as Interner>::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, - ) -> Result<Candidate<I>, NoSolution> { + assumption: I::Clause, + ) -> Result<(), NoSolution> { if let Some(host_clause) = assumption.as_host_effect_clause() { if host_clause.def_id() == goal.predicate.def_id() && host_clause.constness().satisfies(goal.predicate.constness) { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, host_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let host_clause = assumption.as_host_effect_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } /// Register additional assumptions for aliases corresponding to `~const` item bounds. @@ -124,7 +123,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, - impl_def_id: <I as Interner>::DefId, + impl_def_id: I::DefId, ) -> Result<Candidate<I>, NoSolution> { let cx = ecx.cx(); @@ -178,7 +177,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, - _guar: <I as Interner>::ErrorGuaranteed, + _guar: I::ErrorGuaranteed, ) -> Result<Candidate<I>, NoSolution> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 65b10e4f23f..36f68808a2c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -132,12 +132,14 @@ where (Certainty::Yes, NestedNormalizationGoals(goals)) } _ => { - let certainty = shallow_certainty.unify_with(goals_certainty); + let certainty = shallow_certainty.and(goals_certainty); (certainty, NestedNormalizationGoals::empty()) } }; - if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty { + if let Certainty::Maybe(cause @ MaybeCause::Overflow { keep_constraints: false, .. }) = + certainty + { // If we have overflow, it's probable that we're substituting a type // into itself infinitely and any partial substitutions in the query // response are probably not useful anyways, so just return an empty @@ -193,6 +195,7 @@ where debug!(?num_non_region_vars, "too many inference variables -> overflow"); return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow { suggest_increasing_limit: true, + keep_constraints: false, })); } } @@ -250,13 +253,7 @@ where // to the `var_values`. let opaque_types = self .delegate - .clone_opaque_types_lookup_table() - .into_iter() - .filter(|(a, _)| { - self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) - }) - .chain(self.delegate.clone_duplicate_opaque_types()) - .collect(); + .clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries); ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c13e7308055..fc5dad9a3ed 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -23,8 +23,7 @@ use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, - HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput, - QueryResult, + HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, }; pub(super) mod canonical; @@ -99,8 +98,6 @@ where current_goal_kind: CurrentGoalKind, pub(super) var_values: CanonicalVarValues<I>, - predefined_opaques_in_body: I::PredefinedOpaques, - /// The highest universe index nameable by the caller. /// /// When we enter a new binder inside of the query we create new universes @@ -111,6 +108,10 @@ where /// if we have a coinductive cycle and because that's the only way we can return /// new placeholders to the caller. pub(super) max_input_universe: ty::UniverseIndex, + /// The opaque types from the canonical input. We only need to return opaque types + /// which have been added to the storage while evaluating this goal. + pub(super) initial_opaque_types_storage_num_entries: + <D::Infcx as InferCtxtLike>::OpaqueTypeStorageEntries, pub(super) search_graph: &'a mut SearchGraph<D>, @@ -305,10 +306,8 @@ where // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. - predefined_opaques_in_body: delegate - .cx() - .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()), max_input_universe: ty::UniverseIndex::ROOT, + initial_opaque_types_storage_num_entries: Default::default(), variables: Default::default(), var_values: CanonicalVarValues::dummy(), current_goal_kind: CurrentGoalKind::Misc, @@ -342,25 +341,10 @@ where canonical_goal_evaluation: &mut ProofTreeBuilder<D>, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R, ) -> R { - let (ref delegate, input, var_values) = - SolverDelegate::build_with_canonical(cx, &canonical_input); - - let mut ecx = EvalCtxt { - delegate, - variables: canonical_input.canonical.variables, - var_values, - current_goal_kind: CurrentGoalKind::from_query_input(cx, input), - predefined_opaques_in_body: input.predefined_opaques_in_body, - max_input_universe: canonical_input.canonical.max_universe, - search_graph, - nested_goals: Default::default(), - origin_span: I::Span::dummy(), - tainted: Ok(()), - inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), - }; + let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input); for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span); + let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy()); // It may be possible that two entries in the opaque type storage end up // with the same key after resolving contained inference variables. // @@ -373,13 +357,24 @@ where // the canonical input. This is more annoying to implement and may cause a // perf regression, so we do it inside of the query for now. if let Some(prev) = prev { - debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_type_storage`"); + debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`"); } } - if !ecx.nested_goals.is_empty() { - panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals); - } + let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries(); + let mut ecx = EvalCtxt { + delegate, + variables: canonical_input.canonical.variables, + var_values, + current_goal_kind: CurrentGoalKind::from_query_input(cx, input), + max_input_universe: canonical_input.canonical.max_universe, + initial_opaque_types_storage_num_entries, + search_graph, + nested_goals: Default::default(), + origin_span: I::Span::dummy(), + tainted: Ok(()), + inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), + }; let result = f(&mut ecx, input.goal); ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe); @@ -666,7 +661,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, with_resolved_vars)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } else { @@ -680,7 +675,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, goal)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } @@ -1000,6 +995,14 @@ where self.delegate.resolve_vars_if_possible(value) } + pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region { + if let ty::ReVar(vid) = r.kind() { + self.delegate.opportunistic_resolve_lt_var(vid) + } else { + r + } + } + pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { let args = self.delegate.fresh_args_for_item(def_id); for arg in args.iter() { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index 0a9e7fafaea..ed0cedc4077 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -26,32 +26,33 @@ where I: Interner, { pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T { - let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; + let ProbeCtxt { ecx: outer, probe_kind, _result } = self; - let delegate = outer_ecx.delegate; - let max_input_universe = outer_ecx.max_input_universe; - let mut nested_ecx = EvalCtxt { + let delegate = outer.delegate; + let max_input_universe = outer.max_input_universe; + let mut nested = EvalCtxt { delegate, - variables: outer_ecx.variables, - var_values: outer_ecx.var_values, - current_goal_kind: outer_ecx.current_goal_kind, - predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body, + variables: outer.variables, + var_values: outer.var_values, + current_goal_kind: outer.current_goal_kind, max_input_universe, - search_graph: outer_ecx.search_graph, - nested_goals: outer_ecx.nested_goals.clone(), - origin_span: outer_ecx.origin_span, - tainted: outer_ecx.tainted, - inspect: outer_ecx.inspect.take_and_enter_probe(), + initial_opaque_types_storage_num_entries: outer + .initial_opaque_types_storage_num_entries, + search_graph: outer.search_graph, + nested_goals: outer.nested_goals.clone(), + origin_span: outer.origin_span, + tainted: outer.tainted, + inspect: outer.inspect.take_and_enter_probe(), }; - let r = nested_ecx.delegate.probe(|| { - let r = f(&mut nested_ecx); - nested_ecx.inspect.probe_final_state(delegate, max_input_universe); + let r = nested.delegate.probe(|| { + let r = f(&mut nested); + nested.inspect.probe_final_state(delegate, max_input_universe); r }); - if !nested_ecx.inspect.is_noop() { + if !nested.inspect.is_noop() { let probe_kind = probe_kind(&r); - nested_ecx.inspect.probe_kind(probe_kind); - outer_ecx.inspect = nested_ecx.inspect.finish_probe(); + nested.inspect.probe_kind(probe_kind); + outer.inspect = nested.inspect.finish_probe(); } r } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c9f4fc649b5..8173146e2fe 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -253,16 +253,18 @@ where } fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse<I>]) -> CanonicalResponse<I> { - debug_assert!(!responses.is_empty()); - if let Certainty::Maybe(maybe_cause) = - responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { - certainty.unify_with(response.value.certainty) - }) - { - self.make_ambiguous_response_no_constraints(maybe_cause) - } else { - panic!("expected flounder response to be ambiguous") - } + debug_assert!(responses.len() > 1); + let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| { + // Pull down the certainty of `Certainty::Yes` to ambiguity when combining + // these responses, b/c we're combining more than one response and this we + // don't know which one applies. + let candidate = match response.value.certainty { + Certainty::Yes => MaybeCause::Ambiguity, + Certainty::Maybe(candidate) => candidate, + }; + maybe_cause.or(candidate) + }); + self.make_ambiguous_response_no_constraints(maybe_cause) } /// If we fail to merge responses we flounder and return overflow or ambiguity. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 400b4ce1200..b90e34e7810 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -106,50 +106,48 @@ where self.trait_def_id(cx) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, - ) -> Result<Candidate<I>, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.item_def_id() == goal.predicate.def_id() { - let cx = ecx.cx(); - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.alias.args, projection_pred.skip_binder().projection_term.args, ) { - return Err(NoSolution); + return Ok(()); } - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq( - goal.param_env, - goal.predicate.alias, - assumption_projection_pred.projection_term, - )?; - - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); - - // Add GAT where clauses from the trait's definition - // FIXME: We don't need these, since these are the type's own WF obligations. - ecx.add_goals( - GoalSource::AliasWellFormed, - cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) - .map(|pred| goal.with(cx, pred)), - ); - - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let projection_pred = assumption.as_projection_clause().unwrap(); + + let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; + + ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + + // Add GAT where clauses from the trait's definition + // FIXME: We don't need these, since these are the type's own WF obligations. + let cx = ecx.cx(); + ecx.add_goals( + GoalSource::AliasWellFormed, + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), + ); + + Ok(()) } fn consider_additional_alias_assumptions( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d19249df387..e3addf8bf93 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -17,7 +17,7 @@ use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidates use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, + NoSolution, ParamEnvSource, }; impl<D, I> assembly::GoalKind<D> for TraitPredicate<I> @@ -125,39 +125,38 @@ where .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource<I>, goal: Goal<I, Self>, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>, - ) -> Result<Candidate<I>, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, trait_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let trait_clause = assumption.as_trait_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } fn consider_auto_trait_candidate( @@ -1253,10 +1252,9 @@ where D: SolverDelegate<Interner = I>, I: Interner, { - #[instrument(level = "debug", skip(self, goal), ret)] + #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, - goal: Goal<I, TraitPredicate<I>>, mut candidates: Vec<Candidate<I>>, ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> { if let TypingMode::Coherence = self.typing_mode() { @@ -1284,21 +1282,9 @@ where // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. - let has_non_global_where_bounds = candidates.iter().any(|c| match c.source { - CandidateSource::ParamEnv(idx) => { - let where_bound = goal.param_env.caller_bounds().get(idx).unwrap(); - let ty::ClauseKind::Trait(trait_pred) = where_bound.kind().skip_binder() else { - unreachable!("expected trait-bound: {where_bound:?}"); - }; - - if trait_pred.has_bound_vars() || !trait_pred.is_global() { - return true; - } - - false - } - _ => false, - }); + let has_non_global_where_bounds = candidates + .iter() + .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal))); if has_non_global_where_bounds { let where_bounds: Vec<_> = candidates .iter() @@ -1331,13 +1317,16 @@ where // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the // remaining candidates. - let proven_via = - if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) { - TraitGoalProvenVia::ParamEnv - } else { - candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_))); - TraitGoalProvenVia::Misc - }; + let proven_via = if candidates + .iter() + .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))) + { + TraitGoalProvenVia::ParamEnv + } else { + candidates + .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); + TraitGoalProvenVia::Misc + }; let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&all_candidates) { @@ -1353,7 +1342,7 @@ where goal: Goal<I, TraitPredicate<I>>, ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> { let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); - self.merge_trait_candidates(goal, candidates) + self.merge_trait_candidates(candidates) } fn try_stall_coroutine_witness( diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 3d7e0fcc308..f88c15785d3 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -690,8 +690,8 @@ parse_nul_in_c_str = null characters in C string literals are not supported parse_or_in_let_chain = `||` operators are not supported in let chain conditions -parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters -parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings +parse_or_pattern_not_allowed_in_fn_parameters = function parameters require top-level or-patterns in parentheses +parse_or_pattern_not_allowed_in_let_binding = `let` bindings require top-level or-patterns in parentheses parse_out_of_range_hex_escape = out of range hex escape .label = must be a character in the range [\x00-\x7f] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index d06922f1e04..3ab726d9d9d 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -4,7 +4,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(debug_closure_helpers)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f3b53971b29..2a7910a6af4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3828,7 +3828,7 @@ impl<'a> Parser<'a> { // Convert `label` -> `'label`, // so that nameres doesn't complain about non-existing label let label = format!("'{}", ident.name); - let ident = Ident { name: Symbol::intern(&label), span: ident.span }; + let ident = Ident::new(Symbol::intern(&label), ident.span); self.dcx().emit_err(errors::ExpectedLabelFoundIdent { span: ident.span, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 001725e2882..f9445485f60 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(box_patterns)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a3b479fdb7a..9c2921cd5b2 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(associated_type_defaults)] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index b159b876c7e..eba7378b475 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(rustc::potential_query_instability, internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(assert_matches)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 0fcc3d8f6b3..a97e0eaa9c6 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -11,6 +11,7 @@ pulldown-cmark = { version = "0.11", features = ["html"], default-features = fal rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index cb328022c76..3460c53782f 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -549,7 +549,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { source = module_path.pop().unwrap(); if rename.is_none() { // Keep the span of `self`, but the name of `foo` - ident = Ident { name: source.ident.name, span: self_span }; + ident = Ident::new(source.ident.name, self_span); } } } else { @@ -597,7 +597,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if let Some(crate_name) = crate_name { // `crate_name` should not be interpreted as relative. module_path.push(Segment::from_ident_and_id( - Ident { name: kw::PathRoot, span: source.ident.span }, + Ident::new(kw::PathRoot, source.ident.span), self.r.next_node_id(), )); source.ident.name = crate_name; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 74daad08394..0b16983c2c7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -5,6 +5,7 @@ use rustc_ast::{ self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path, }; use rustc_ast_pretty::pprust; +use rustc_attr_data_structures::{self as attr, Stability}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -110,6 +111,7 @@ pub(crate) struct ImportSuggestion { pub via_import: bool, /// An extra note that should be issued if this item is suggested pub note: Option<String>, + pub is_stable: bool, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -1172,13 +1174,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ThinVec::<ast::PathSegment>::new(), true, start_did.is_local() || !self.tcx.is_doc_hidden(start_did), + true, )]; let mut worklist_via_import = vec![]; - while let Some((in_module, path_segments, accessible, doc_visible)) = match worklist.pop() { - None => worklist_via_import.pop(), - Some(x) => Some(x), - } { + while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) = + match worklist.pop() { + None => worklist_via_import.pop(), + Some(x) => Some(x), + } + { let in_module_is_extern = !in_module.def_id().is_local(); in_module.for_each_child(self, |this, ident, ns, name_binding| { // Avoid non-importable candidates. @@ -1258,6 +1263,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { candidates.remove(idx); } + let is_stable = if is_stable + && let Some(did) = did + && this.is_stable(did, path.span) + { + true + } else { + false + }; + + // Rreplace unstable suggestions if we meet a new stable one, + // and do nothing if any other situation. For example, if we + // meet `std::ops::Range` after `std::range::legacy::Range`, + // we will remove the latter and then insert the former. + if is_stable + && let Some(idx) = candidates + .iter() + .position(|v: &ImportSuggestion| v.did == did && !v.is_stable) + { + candidates.remove(idx); + } + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { // See if we're recommending TryFrom, TryInto, or FromIterator and add // a note about editions @@ -1289,6 +1315,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { doc_visible: child_doc_visible, note, via_import, + is_stable, }); } } @@ -1315,8 +1342,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if !is_extern_crate_that_also_appears_in_prelude || alias_import { // add the module to the lookup if seen_modules.insert(module.def_id()) { - if via_import { &mut worklist_via_import } else { &mut worklist } - .push((module, path_segments, child_accessible, child_doc_visible)); + if via_import { &mut worklist_via_import } else { &mut worklist }.push( + ( + module, + path_segments, + child_accessible, + child_doc_visible, + is_stable && this.is_stable(module.def_id(), name_binding.span), + ), + ); } } } @@ -1326,6 +1360,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { candidates } + fn is_stable(&self, did: DefId, span: Span) -> bool { + if did.is_local() { + return true; + } + + match self.tcx.lookup_stability(did) { + Some(Stability { + level: attr::StabilityLevel::Unstable { implied_by, .. }, + feature, + .. + }) => { + if span.allows_unstable(feature) { + true + } else if self.tcx.features().enabled(feature) { + true + } else if let Some(implied_by) = implied_by + && self.tcx.features().enabled(implied_by) + { + true + } else { + false + } + } + Some(_) => true, + None => false, + } + } + /// When name resolution fails, this method can be used to look up candidate /// entities with the expected name. It allows filtering them using the /// supplied predicate (which should be used to only accept the types of diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d4fe446cc9f..b538be34f31 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2501,6 +2501,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { doc_visible, note: None, via_import: false, + is_stable: true, }, )); } else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7e516d82df1..9ba70abd4d9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -10,7 +10,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -2157,13 +2156,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns: Namespace, parent_scope: ParentScope<'ra>, ) -> Option<Res> { - let mut segments = - Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); - if let Some(segment) = segments.first_mut() { - if segment.ident.name == kw::Empty { - segment.ident.name = kw::PathRoot; - } - } + let segments: Result<Vec<_>, ()> = path_str + .split("::") + .enumerate() + .map(|(i, s)| { + let sym = if s.is_empty() { + if i == 0 { + // For a path like `::a::b`, use `kw::PathRoot` as the leading segment. + kw::PathRoot + } else { + return Err(()); // occurs in cases like `String::` + } + } else { + Symbol::intern(s) + }; + Ok(Segment::from_ident(Ident::with_dummy_span(sym))) + }) + .collect(); + let Ok(segments) = segments else { return None }; match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()), diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f7f354d12e8..47831f2f418 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -722,6 +722,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) + | hir::definitions::DefPathData::OpaqueLifetime(..) | hir::definitions::DefPathData::LifetimeNs(..) | hir::definitions::DefPathData::AnonAssocTy(..) => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs index 729c921450e..7d7c1c8284d 100644 --- a/compiler/rustc_sanitizers/src/lib.rs +++ b/compiler/rustc_sanitizers/src/lib.rs @@ -4,7 +4,6 @@ //! compiler. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(let_chains))] // tidy-alphabetical-end pub mod cfi; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index ec8e9898dc7..5e5872ee068 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(default_field_values)] #![feature(iter_intersperse)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b95ebfbe89f..5b4068740a1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2408,10 +2408,8 @@ options! { "print codegen statistics (default: no)"), print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), - print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED], - "print the result of the monomorphization collection pass. \ - Value `lazy` means to use normal collection; `eager` means to collect all items. - Note that this overwrites the effect `-Clink-dead-code` has on collection!"), + print_mono_items: bool = (false, parse_bool, [UNTRACKED], + "print the result of the monomorphization collection pass (default: no)"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 61c96e67c17..22ca8accf9f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,7 +17,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 40cec408308..3a95447308a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1301,6 +1301,10 @@ symbols! { match_beginning_vert, match_default_bindings, matches_macro, + maximumf128, + maximumf16, + maximumf32, + maximumf64, maxnumf128, maxnumf16, maxnumf32, @@ -1335,6 +1339,10 @@ symbols! { min_generic_const_args, min_specialization, min_type_alias_impl_trait, + minimumf128, + minimumf16, + minimumf32, + minimumf64, minnumf128, minnumf16, minnumf32, @@ -2099,7 +2107,6 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", - time, tmm_reg, to_owned_method, to_string, @@ -2342,6 +2349,9 @@ pub const STDLIB_STABLE_CRATES: &[Symbol] = &[sym::std, sym::core, sym::alloc, s #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)] pub struct Ident { + // `name` should never be the empty symbol. If you are considering that, + // you are probably conflating "empty identifer with "no identifier" and + // you should use `Option<Ident>` instead. pub name: Symbol, pub span: Span, } @@ -2349,28 +2359,21 @@ pub struct Ident { impl Ident { #[inline] /// Constructs a new identifier from a symbol and a span. - pub const fn new(name: Symbol, span: Span) -> Ident { + pub fn new(name: Symbol, span: Span) -> Ident { + debug_assert_ne!(name, kw::Empty); Ident { name, span } } /// Constructs a new identifier with a dummy span. #[inline] - pub const fn with_dummy_span(name: Symbol) -> Ident { + pub fn with_dummy_span(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) } - /// This is best avoided, because it blurs the lines between "empty - /// identifier" and "no identifier". Using `Option<Ident>` is preferable, - /// where possible, because that is unambiguous. - #[inline] - pub fn empty() -> Ident { - Ident::with_dummy_span(kw::Empty) - } - // For dummy identifiers that are never used and absolutely must be - // present, it's better to use `Ident::dummy` than `Ident::Empty`, because - // it's clearer that it's intended as a dummy value, and more likely to be - // detected if it accidentally does get used. + // present. Note that this does *not* use the empty symbol; `sym::dummy` + // makes it clear that it's intended as a dummy value, and is more likely + // to be detected if it accidentally does get used. #[inline] pub fn dummy() -> Ident { Ident::with_dummy_span(sym::dummy) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index a51d7da878a..a9bf5eae445 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -89,7 +89,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 1f45440eecf..4a99ce09b39 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -890,6 +890,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::Impl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) + | DefPathData::OpaqueLifetime(_) | DefPathData::AnonAssocTy(..) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 922c18448d5..566bee75c7f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,7 +9,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_target/src/spec/base/msvc.rs b/compiler/rustc_target/src/spec/base/msvc.rs index 486d7158723..bd59678d236 100644 --- a/compiler/rustc_target/src/spec/base/msvc.rs +++ b/compiler/rustc_target/src/spec/base/msvc.rs @@ -5,7 +5,19 @@ use crate::spec::{BinaryFormat, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo pub(crate) fn opts() -> TargetOptions { // Suppress the verbose logo and authorship debugging output, which would needlessly // clog any log files. - let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]); + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Msvc(Lld::No), + &[ + "/NOLOGO", + // "Symbol is marked as dllimport, but defined in an object file" + // Harmless warning that flags a potential performance improvement: marking a symbol as + // dllimport indirects usage via the `__imp_` symbol, which isn't required if the symbol + // is in the current binary. This is tripped by __rust_no_alloc_shim_is_unstable as it + // is generated by the compiler, but marked as a foreign item (hence the dllimport) in + // the standard library. + "/IGNORE:4286", + ], + ); TargetOptions { linker_flavor: LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 98d78520c98..c5704c57448 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,10 +1,21 @@ -use crate::spec::{Target, TargetMetadata, base}; +use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); + // Microsoft recommends enabling frame pointers on Arm64 Windows. + // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers + // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW + // and other services. It must point to the previous {x29, x30} pair on the stack." + base.frame_pointer = FramePointer::NonLeaf; + + // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see + // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM. + // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning. + base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/arm64hazardfree"]); + Target { llvm_target: "aarch64-pc-windows-msvc".into(), metadata: TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index bb3e3e544cb..8f93523909e 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, add_link_args, base}; +use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, add_link_args, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); @@ -10,6 +10,12 @@ pub(crate) fn target() -> Target { &["/machine:arm64ec", "softintrin.lib"], ); + // Microsoft recommends enabling frame pointers on Arm64 Windows. + // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers + // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW + // and other services. It must point to the previous {x29, x30} pair on the stack." + base.frame_pointer = FramePointer::NonLeaf; + Target { llvm_target: "arm64ec-pc-windows-msvc".into(), metadata: TargetMetadata { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 5a21925ba04..5428aa4cf70 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -693,17 +693,17 @@ static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("d", Unstable(sym::loongarch_target_feature), &["f"]), + ("d", Stable, &["f"]), ("div32", Unstable(sym::loongarch_target_feature), &[]), - ("f", Unstable(sym::loongarch_target_feature), &[]), - ("frecipe", Unstable(sym::loongarch_target_feature), &[]), + ("f", Stable, &[]), + ("frecipe", Stable, &[]), ("lam-bh", Unstable(sym::loongarch_target_feature), &[]), ("lamcas", Unstable(sym::loongarch_target_feature), &[]), - ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]), - ("lbt", Unstable(sym::loongarch_target_feature), &[]), + ("lasx", Stable, &["lsx"]), + ("lbt", Stable, &[]), ("ld-seq-sa", Unstable(sym::loongarch_target_feature), &[]), - ("lsx", Unstable(sym::loongarch_target_feature), &["d"]), - ("lvz", Unstable(sym::loongarch_target_feature), &[]), + ("lsx", Stable, &["d"]), + ("lvz", Stable, &[]), ("relax", Unstable(sym::loongarch_target_feature), &[]), ("scq", Unstable(sym::loongarch_target_feature), &[]), ("ual", Unstable(sym::loongarch_target_feature), &[]), diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index cf6dd40718b..00922c6038e 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -452,8 +452,6 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point -trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` - trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index de9a50f1962..cb1c9c75369 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -17,7 +17,7 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults, }; -use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym}; use tracing::{debug, instrument, warn}; use super::nice_region_error::placeholder_error::Highlighted; @@ -438,7 +438,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: false, path: Default::default(), - time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -630,10 +629,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } - - let time_version = - self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); - match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -645,7 +640,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.is_some(), path: path.unwrap_or_default(), - time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -671,42 +665,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } - - /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. - /// <https://github.com/rust-lang/rust/issues/127343> - // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. - fn detect_old_time_crate_version( - &self, - span: Option<Span>, - kind: &InferSourceKind<'_>, - // We will clear the non-actionable suggestion from the error to reduce noise. - infer_subdiags: &mut Vec<SourceKindSubdiag<'_>>, - ) -> bool { - // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing - // compilation once we promote 1.89 to beta, which will happen in 9 months from now. - #[cfg(not(version("1.89")))] - const fn version_check() {} - #[cfg(version("1.89"))] - const fn version_check() { - panic!("remove this check as presumably the ecosystem has moved from needing it"); - } - const { version_check() }; - // Only relevant when building the `time` crate. - if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time - && let Some(span) = span - && let InferSourceKind::LetBinding { pattern_name, .. } = kind - && let Some(name) = pattern_name - && name.as_str() == "items" - && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) - { - let path = file.local_path_if_available().to_string_lossy(); - if path.contains("format_description") && path.contains("parse") { - infer_subdiags.clear(); - return true; - } - } - false - } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index d8b90844b7d..ce170f820e1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -20,7 +20,7 @@ pub struct FormatString { input: Symbol, span: Span, pieces: Vec<Piece>, - /// The formatting string was parsed succesfully but with warnings + /// The formatting string was parsed successfully but with warnings pub warnings: Vec<FormatWarning>, } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index de251ae2893..8801397b775 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1516,6 +1516,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { expr.span.with_hi(expr.span.lo() + BytePos(1)) }; + + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(snippet) if snippet.starts_with("&") => {} + _ => break 'outer, + } + suggestions.push((span, String::new())); let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else { diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 04cae1c9b64..8ab4d795c45 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -219,8 +219,6 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: bool, pub path: PathBuf, - #[note(trait_selection_type_annotations_needed_error_time)] - pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 7613a0cef52..67328defe36 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -14,7 +14,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 87b8db59a78..3601c2cba9b 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -104,25 +104,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect()) } - fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.0 - .inner - .borrow_mut() - .opaque_types() - .iter_lookup_table() - .map(|(k, h)| (k, h.ty)) - .collect() - } - fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.0 - .inner - .borrow_mut() - .opaque_types() - .iter_duplicate_entries() - .map(|(k, h)| (k, h.ty)) - .collect() - } - fn make_deduplicated_outlives_constraints( &self, ) -> Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> { @@ -168,30 +149,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.instantiate_canonical_var(span, cv_info, universe_map) } - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey<'tcx>, - hidden_ty: Ty<'tcx>, - span: Span, - ) -> Option<Ty<'tcx>> { - self.0.register_hidden_type_in_storage( - opaque_type_key, - ty::OpaqueHiddenType { span, ty: hidden_ty }, - ) - } - fn add_duplicate_opaque_type( - &self, - opaque_type_key: ty::OpaqueTypeKey<'tcx>, - hidden_ty: Ty<'tcx>, - span: Span, - ) { - self.0 - .inner - .borrow_mut() - .opaque_types() - .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty }) - } - fn add_item_bounds_for_hidden_type( &self, def_id: DefId, @@ -203,10 +160,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals); } - fn reset_opaque_types(&self) { - let _ = self.take_opaque_types(); - } - fn fetch_eligible_assoc_item( &self, goal_trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 2d445dd0790..f64cd5ffebe 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -99,7 +99,13 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + Ok(( + _, + Certainty::Maybe(MaybeCause::Overflow { + suggest_increasing_limit, + keep_constraints: _, + }), + )) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. // We discard the inference constraints from overflowing goals, so diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 24b87000e32..9795655e842 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -382,7 +382,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { if let Some(term_hack) = normalizes_to_term_hack { infcx .probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env)) - .map(|certainty| ok.value.certainty.unify_with(certainty)) + .map(|certainty| ok.value.certainty.and(certainty)) } else { Ok(ok.value.certainty) } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index a54eb80fedc..eb34cb10c68 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -9,7 +9,7 @@ use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_span::DUMMY_SP; use tracing::{debug, info, instrument}; @@ -127,7 +127,7 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) { self.outer_index.shift_in(1); t.super_visit_with(self); self.outer_index.shift_out(1); diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index f79b6d44bfd..929cc074bda 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(let_chains))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 31d69eef5ec..0c49ddff39b 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -7,7 +7,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, + fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; @@ -185,7 +186,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { } impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, binder: &ty::Binder<'tcx, T>) { + fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, binder: &ty::Binder<'tcx, T>) { self.depth.shift_in(1); binder.super_visit_with(self); self.depth.shift_out(1); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 27ea4e211fe..000cf1e1fd8 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -128,7 +128,7 @@ impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Binder<I, T> { } } -impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Binder<I, T> { +impl<I: Interner, T: TypeFoldable<I>> TypeVisitable<I> for Binder<I, T> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } @@ -147,7 +147,7 @@ impl<I: Interner, T: TypeFoldable<I>> TypeSuperFoldable<I> for Binder<I, T> { } } -impl<I: Interner, T: TypeVisitable<I>> TypeSuperVisitable<I> for Binder<I, T> { +impl<I: Interner, T: TypeFoldable<I>> TypeSuperVisitable<I> for Binder<I, T> { fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } @@ -292,7 +292,7 @@ impl<I: Interner> ValidateBoundVars<I> { impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> { type Result = ControlFlow<()>; - fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &Binder<I, T>) -> Self::Result { + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &Binder<I, T>) -> Self::Result { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 7d2654de440..c1490762117 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; @@ -245,4 +247,32 @@ pub trait InferCtxtLike: Sized { r: <Self::Interner as Interner>::Region, span: <Self::Interner as Interner>::Span, ); + + type OpaqueTypeStorageEntries: Debug + Copy + Default; + fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; + fn clone_opaque_types_lookup_table( + &self, + ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>; + fn clone_duplicate_opaque_types( + &self, + ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>; + fn clone_opaque_types_added_since( + &self, + prev_entries: Self::OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>; + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey<Self::Interner>, + hidden_ty: <Self::Interner as Interner>::Ty, + span: <Self::Interner as Interner>::Span, + ) -> Option<<Self::Interner as Interner>::Ty>; + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey<Self::Interner>, + hidden_ty: <Self::Interner as Interner>::Ty, + span: <Self::Interner as Interner>::Span, + ); + + fn reset_opaque_types(&self); } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 4e9b87fdf74..2e05c23a645 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -147,9 +147,8 @@ pub enum CandidateSource<I: Interner> { /// 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`. + /// An assumption from the environment. Stores a [`ParamEnvSource`], since we + /// prefer non-global param-env candidates in candidate assembly. /// /// ## Examples /// @@ -160,7 +159,7 @@ pub enum CandidateSource<I: Interner> { /// (x.clone(), x) /// } /// ``` - ParamEnv(usize), + ParamEnv(ParamEnvSource), /// 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. @@ -190,6 +189,14 @@ pub enum CandidateSource<I: Interner> { } #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub enum ParamEnvSource { + /// Preferred eagerly. + NonGlobal, + // Not considered unless there are non-global param-env candidates too. + Global, +} + +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr( feature = "nightly", derive(HashStable_NoContext, Encodable_NoContext, Decodable_NoContext) @@ -266,17 +273,17 @@ impl Certainty { /// 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 { + pub fn and(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)), + (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.and(b)), } } pub const fn overflow(suggest_increasing_limit: bool) -> Certainty { - Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }) + Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: false }) } } @@ -289,19 +296,58 @@ pub enum MaybeCause { /// 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 }, + Overflow { suggest_increasing_limit: bool, keep_constraints: bool }, } impl MaybeCause { - fn unify_with(self, other: MaybeCause) -> MaybeCause { + fn and(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 }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a && limit_b, + keep_constraints: keep_a && keep_b, + }, + } + } + + pub fn or(self, other: MaybeCause) -> MaybeCause { + match (self, other) { + (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, + + // When combining ambiguity + overflow, we can keep constraints. + ( + MaybeCause::Ambiguity, + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + ( + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + MaybeCause::Ambiguity, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + + ( + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a || limit_b, + keep_constraints: keep_a || keep_b, + }, } } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fb..8ba985d2d19 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -342,7 +342,7 @@ struct HasRegionsBoundAt { // FIXME: Could be optimized to not walk into components with no escaping bound vars. impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt { type Result = ControlFlow<()>; - fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { self.binder.shift_in(1); t.super_visit_with(self)?; self.binder.shift_out(1); diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 2285e0e75de..ccb84e25911 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, TypeFlags}; +use crate::{self as ty, Interner, TypeFlags, TypeFoldable}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -94,7 +94,7 @@ pub trait TypeVisitor<I: Interner>: Sized { #[cfg(not(feature = "nightly"))] type Result: VisitorResult; - fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { t.super_visit_with(self) } @@ -401,7 +401,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor { type Result = ControlFlow<FoundFlags>; - fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { // If we're looking for the HAS_BINDER_VARS flag, check if the // binder has vars. This won't be present in the binder's bound // value, so we need to check here too. @@ -510,7 +510,7 @@ struct HasEscapingVarsVisitor { impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor { type Result = ControlFlow<FoundEscapingVars>; - fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { + fn visit_binder<T: TypeFoldable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); |
