Rollup merge of #139167 - Amanieu:remove-amanieu, r=Mark-Simulacrum
Remove Amanieu from the libs review rotation
Unfortunately I've accumulated a large backlog of PRs to review, both in rust-lang and my own repos. Until I've cleared the backlog, I will remove myself from the review rotation for rust-lang/rust.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 5f8941d..dc00b52 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -294,7 +294,7 @@ pub fn def_path_data(self, name: Option<Symbol>) -> DefPathData {
DefKind::GlobalAsm => DefPathData::GlobalAsm,
DefKind::Impl { .. } => DefPathData::Impl,
DefKind::Closure => DefPathData::Closure,
- DefKind::SyntheticCoroutineBody => DefPathData::Closure,
+ DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
}
}
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 61f5efd..c52954a 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -291,6 +291,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
+ /// A synthetic body for a coroutine's by-move body.
+ SyntheticCoroutineBody,
}
impl Definitions {
@@ -415,8 +417,16 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
- Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
- | OpaqueTy => None,
+ Impl
+ | ForeignMod
+ | CrateRoot
+ | Use
+ | GlobalAsm
+ | Closure
+ | Ctor
+ | AnonConst
+ | OpaqueTy
+ | SyntheticCoroutineBody => None,
}
}
@@ -441,6 +451,7 @@ pub fn name(&self) -> DefPathDataName {
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
+ SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
}
}
}
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 0cc72a2..00da1a6 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -172,6 +172,8 @@ pub const fn new() -> CodegenFnAttrs {
/// * `#[no_mangle]` is present
/// * `#[export_name(...)]` is present
/// * `#[linkage]` is present
+ ///
+ /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
pub fn contains_extern_indicator(&self) -> bool {
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 83ada5c..1ffe958 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -150,6 +150,7 @@ pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
// If the function is #[naked] or contains any other attribute that requires exactly-once
// instantiation:
+ // We emit an unused_attributes lint for this case, which should be kept in sync if possible.
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 811bd8f..aa2ee75 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -95,10 +95,16 @@
/// parameter environment.
#[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)]
pub enum SelectionCandidate<'tcx> {
+ /// A built-in implementation for the `Sized` trait. This is preferred
+ /// over all other candidates.
+ SizedCandidate {
+ has_nested: bool,
+ },
+
/// A builtin implementation for some specific traits, used in cases
/// where we cannot rely an ordinary library implementations.
///
- /// The most notable examples are `sized`, `Copy` and `Clone`. This is also
+ /// The most notable examples are `Copy` and `Clone`. This is also
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
/// an associated type.
BuiltinCandidate {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 08d4c1f..618a65a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1930,10 +1930,10 @@ pub fn create_def(
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
// comp. engine itself.
//
- // This call also writes to the value of `source_span` and `expn_that_defined` queries.
+ // This call also writes to the value of the `source_span` query.
// This is fine because:
- // - those queries are `eval_always` so we won't miss their result changing;
- // - this write will have happened before these queries are called.
+ // - that query is `eval_always` so we won't miss its result changing;
+ // - this write will have happened before that query is called.
let def_id = self.untracked.definitions.write().create_def(parent, data);
// This function modifies `self.definitions` using a side-effect.
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index dc2040a..5904dea 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -139,8 +139,7 @@ fn default_print_def_path(
match key.disambiguated_data.data {
DefPathData::Closure => {
- // FIXME(async_closures): This is somewhat ugly.
- // We need to additionally print the `kind` field of a closure if
+ // We need to additionally print the `kind` field of a coroutine if
// it is desugared from a coroutine-closure.
if let Some(hir::CoroutineKind::Desugared(
_,
@@ -156,6 +155,10 @@ fn default_print_def_path(
// Closures' own generics are only captures, don't print them.
}
}
+ DefPathData::SyntheticCoroutineBody => {
+ // Synthetic coroutine bodies have no distinct generics, since like
+ // closures they're all just internal state of the coroutine.
+ }
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
// Anon consts doesn't have their own generics, and inline consts' own
// generics are their inferred types, so don't print them.
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index f813c33..1b4341e 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -810,16 +810,16 @@ pub(crate) enum WrapInParentheses {
#[derive(Diagnostic)]
#[diag(parse_array_brackets_instead_of_braces)]
-pub(crate) struct ArrayBracketsInsteadOfSpaces {
+pub(crate) struct ArrayBracketsInsteadOfBraces {
#[primary_span]
pub span: Span,
#[subdiagnostic]
- pub sub: ArrayBracketsInsteadOfSpacesSugg,
+ pub sub: ArrayBracketsInsteadOfBracesSugg,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
-pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
+pub(crate) struct ArrayBracketsInsteadOfBracesSugg {
#[suggestion_part(code = "[")]
pub left: Span,
#[suggestion_part(code = "]")]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 92e8357..00e75cc 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2200,7 +2200,9 @@ pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
}
fn is_array_like_block(&mut self) -> bool {
- self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
+ matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+ && self
+ .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
&& self.look_ahead(2, |t| t == &token::Comma)
&& self.look_ahead(3, |t| t.can_begin_expr())
}
@@ -2212,9 +2214,9 @@ fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Exp
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
Ok(arr) => {
- let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces {
+ let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
span: arr.span,
- sub: errors::ArrayBracketsInsteadOfSpacesSugg {
+ sub: errors::ArrayBracketsInsteadOfBracesSugg {
left: lo,
right: snapshot.prev_token.span,
},
@@ -2337,7 +2339,8 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
let capture_clause = self.parse_capture_clause()?;
let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
let decl_hi = self.prev_token.span;
- let mut body = match fn_decl.output {
+ let mut body = match &fn_decl.output {
+ // No return type.
FnRetTy::Default(_) => {
let restrictions =
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
@@ -2349,11 +2352,8 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
}
}
- _ => {
- // If an explicit return type is given, require a block to appear (RFC 968).
- let body_lo = self.token.span;
- self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
- }
+ // Explicit return type (`->`) needs block `-> T { }`.
+ FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
};
match coroutine_kind {
@@ -2405,6 +2405,49 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
Ok(closure)
}
+ /// If an explicit return type is given, require a block to appear (RFC 968).
+ fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
+ if self.may_recover()
+ && self.token.can_begin_expr()
+ && !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+ && !self.token.is_whole_block()
+ {
+ let snapshot = self.create_snapshot_for_diagnostic();
+ let restrictions =
+ self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
+ let tok = self.token.clone();
+ match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
+ Ok((expr, _)) => {
+ let descr = super::token_descr(&tok);
+ let mut diag = self
+ .dcx()
+ .struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
+ diag.span_label(
+ ret_span,
+ "explicit return type requires closure body to be enclosed in braces",
+ );
+ diag.multipart_suggestion_verbose(
+ "wrap the expression in curly braces",
+ vec![
+ (expr.span.shrink_to_lo(), "{ ".to_string()),
+ (expr.span.shrink_to_hi(), " }".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ diag.emit();
+ return Ok(expr);
+ }
+ Err(diag) => {
+ diag.cancel();
+ self.restore_snapshot(snapshot);
+ }
+ }
+ }
+
+ let body_lo = self.token.span;
+ self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
+ }
+
/// Parses an optional `move` or `use` prefix to a closure-like construct.
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
if self.eat_keyword(exp!(Move)) {
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 06398dd..bea8680 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -383,6 +383,10 @@
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "65833")}
+passes_inline_ignored_for_exported =
+ `#[inline]` is ignored on externally exported functions
+ .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
passes_inline_ignored_function_prototype =
`#[inline]` is ignored on function prototypes
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1e1fb42..ada3151 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -451,6 +451,23 @@ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targ
});
}
}
+
+ // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
+ if let Some(did) = hir_id.as_owner()
+ && self.tcx.def_kind(did).has_codegen_attrs()
+ && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never))
+ {
+ let attrs = self.tcx.codegen_fn_attrs(did);
+ // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
+ if attrs.contains_extern_indicator() {
+ self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span(),
+ errors::InlineIgnoredForExported {},
+ );
+ }
+ }
}
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 0ee1743..4e3e032 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1441,6 +1441,11 @@ pub(crate) struct OnlyHasEffectOn {
pub target_name: String,
}
+#[derive(LintDiagnostic)]
+#[diag(passes_inline_ignored_for_exported)]
+#[help]
+pub(crate) struct InlineIgnoredForExported {}
+
#[derive(Diagnostic)]
#[diag(passes_object_lifetime_err)]
pub(crate) struct ObjectLifetimeErr {
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 495f347..127dcd8 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -66,6 +66,7 @@ pub struct MarkFrame<'a> {
parent: Option<&'a MarkFrame<'a>>,
}
+#[derive(Debug)]
pub(super) enum DepNodeColor {
Red,
Green(DepNodeIndex),
@@ -909,7 +910,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
if node_index.is_some() {
- debug!("managed to MARK dependency {dep_dep_node:?} as green",);
+ debug!("managed to MARK dependency {dep_dep_node:?} as green");
return Some(());
}
}
@@ -930,7 +931,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
return Some(());
}
Some(DepNodeColor::Red) => {
- debug!("dependency {dep_dep_node:?} was red after forcing",);
+ debug!("dependency {dep_dep_node:?} was red after forcing");
return None;
}
None => {}
@@ -950,7 +951,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
// invalid state will not be persisted to the
// incremental compilation cache because of
// compilation errors being present.
- debug!("dependency {dep_dep_node:?} resulted in compilation error",);
+ debug!("dependency {dep_dep_node:?} resulted in compilation error");
return None;
}
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 e088417..d56ca9c 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
@@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
hir::definitions::DefPathData::Ctor => "c",
hir::definitions::DefPathData::AnonConst => "k",
hir::definitions::DefPathData::OpaqueTy => "i",
+ hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
hir::definitions::DefPathData::CrateRoot
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 4390085..e7a8dee 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -75,6 +75,21 @@ pub struct SyntaxContextData {
}
impl SyntaxContextData {
+ fn new(
+ (parent, outer_expn, outer_transparency): SyntaxContextKey,
+ opaque: SyntaxContext,
+ opaque_and_semitransparent: SyntaxContext,
+ ) -> SyntaxContextData {
+ SyntaxContextData {
+ outer_expn,
+ outer_transparency,
+ parent,
+ opaque,
+ opaque_and_semitransparent,
+ dollar_crate_name: kw::DollarCrate,
+ }
+ }
+
fn root() -> SyntaxContextData {
SyntaxContextData {
outer_expn: ExpnId::root(),
@@ -543,7 +558,7 @@ fn apply_mark(
) -> SyntaxContext {
assert_ne!(expn_id, ExpnId::root());
if transparency == Transparency::Opaque {
- return self.apply_mark_internal(ctxt, expn_id, transparency);
+ return self.alloc_ctxt(ctxt, expn_id, transparency);
}
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
@@ -554,7 +569,7 @@ fn apply_mark(
};
if call_site_ctxt.is_root() {
- return self.apply_mark_internal(ctxt, expn_id, transparency);
+ return self.alloc_ctxt(ctxt, expn_id, transparency);
}
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
@@ -567,74 +582,60 @@ fn apply_mark(
//
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
for (expn_id, transparency) in self.marks(ctxt) {
- call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
+ call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
}
- self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
+ self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
}
- fn apply_mark_internal(
+ /// Allocate a new context with the given key, or retrieve it from cache if the given key
+ /// already exists. The auxiliary fields are calculated from the key.
+ fn alloc_ctxt(
&mut self,
- ctxt: SyntaxContext,
+ parent: SyntaxContext,
expn_id: ExpnId,
transparency: Transparency,
) -> SyntaxContext {
- let syntax_context_data = &mut self.syntax_context_data;
- debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
- let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
- let mut opaque_and_semitransparent =
- syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
+ debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
- if transparency >= Transparency::Opaque {
- let parent = opaque;
- opaque = *self
- .syntax_context_map
- .entry((parent, expn_id, transparency))
- .or_insert_with(|| {
- let new_opaque = SyntaxContext::from_usize(syntax_context_data.len());
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque: new_opaque,
- opaque_and_semitransparent: new_opaque,
- dollar_crate_name: kw::DollarCrate,
- });
- new_opaque
- });
+ // Look into the cache first.
+ let key = (parent, expn_id, transparency);
+ if let Some(ctxt) = self.syntax_context_map.get(&key) {
+ return *ctxt;
}
- if transparency >= Transparency::SemiTransparent {
- let parent = opaque_and_semitransparent;
- opaque_and_semitransparent = *self
- .syntax_context_map
- .entry((parent, expn_id, transparency))
- .or_insert_with(|| {
- let new_opaque_and_semitransparent =
- SyntaxContext::from_usize(syntax_context_data.len());
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque,
- opaque_and_semitransparent: new_opaque_and_semitransparent,
- dollar_crate_name: kw::DollarCrate,
- });
- new_opaque_and_semitransparent
- });
- }
+ // Reserve a new syntax context.
+ let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len());
+ self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
+ self.syntax_context_map.insert(key, ctxt);
- let parent = ctxt;
- *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque,
- opaque_and_semitransparent,
- dollar_crate_name: kw::DollarCrate,
- });
- SyntaxContext::from_usize(syntax_context_data.len() - 1)
- })
+ // Opaque and semi-transparent versions of the parent. Note that they may be equal to the
+ // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
+ // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
+ // and semi-transparents.
+ let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
+ let parent_opaque_and_semitransparent =
+ self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
+
+ // Evaluate opaque and semi-transparent versions of the new syntax context.
+ let (opaque, opaque_and_semitransparent) = match transparency {
+ Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
+ Transparency::SemiTransparent => (
+ parent_opaque,
+ // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+ self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ ),
+ Transparency::Opaque => (
+ // Will be the same as `ctxt` if the expn chain contains only opaques.
+ self.alloc_ctxt(parent_opaque, expn_id, transparency),
+ // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+ self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ ),
+ };
+
+ // Fill the full data, now that we have it.
+ self.syntax_context_data[ctxt.as_u32() as usize] =
+ SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
+ ctxt
}
}
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 88754f1..2802e89 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
loop {
let key = tcx.def_key(ty_def_id);
match key.disambiguated_data.data {
- DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
+ DefPathData::TypeNs(_)
+ | DefPathData::ValueNs(_)
+ | DefPathData::Closure
+ | DefPathData::SyntheticCoroutineBody => {
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
debug!(?instance_ty);
break;
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index d824a23..99d44bc 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -850,6 +850,7 @@ fn path_append(
DefPathData::Ctor => 'c',
DefPathData::AnonConst => 'k',
DefPathData::OpaqueTy => 'i',
+ DefPathData::SyntheticCoroutineBody => 's',
// These should never show up as `path_append` arguments.
DefPathData::CrateRoot
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 4cfd814..d15c9af 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -86,10 +86,7 @@ pub(super) fn assemble_candidates<'o>(
// `Pointee` is automatically implemented for every type.
candidates.vec.push(BuiltinCandidate { has_nested: false });
} else if tcx.is_lang_item(def_id, LangItem::Sized) {
- // Sized is never implementable by end-users, it is
- // always automatically computed.
- let sized_conditions = self.sized_conditions(obligation);
- self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
+ self.assemble_builtin_sized_candidate(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Unsize) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Destruct) {
@@ -1061,6 +1058,27 @@ fn assemble_candidates_for_trait_alias(
/// Assembles the trait which are built-in to the language itself:
/// `Copy`, `Clone` and `Sized`.
#[instrument(level = "debug", skip(self, candidates))]
+ fn assemble_builtin_sized_candidate(
+ &mut self,
+ obligation: &PolyTraitObligation<'tcx>,
+ candidates: &mut SelectionCandidateSet<'tcx>,
+ ) {
+ match self.sized_conditions(obligation) {
+ BuiltinImplConditions::Where(nested) => {
+ candidates
+ .vec
+ .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
+ }
+ BuiltinImplConditions::None => {}
+ BuiltinImplConditions::Ambiguous => {
+ candidates.ambiguous = true;
+ }
+ }
+ }
+
+ /// Assembles the trait which are built-in to the language itself:
+ /// e.g. `Copy` and `Clone`.
+ #[instrument(level = "debug", skip(self, candidates))]
fn assemble_builtin_bound_candidates(
&mut self,
conditions: BuiltinImplConditions<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index a66c958..6302417 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -40,6 +40,11 @@ pub(super) fn confirm_candidate(
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut impl_src = match candidate {
+ SizedCandidate { has_nested } => {
+ let data = self.confirm_builtin_candidate(obligation, has_nested);
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
+ }
+
BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
ImplSource::Builtin(BuiltinImplSource::Misc, data)
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e439df7..0679dbf 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1801,17 +1801,21 @@ fn winnow_candidates(
return Some(candidates.pop().unwrap().candidate);
}
- // We prefer trivial builtin candidates, i.e. builtin impls without any nested
- // requirements, over all others. This is a fix for #53123 and prevents winnowing
- // from accidentally extending the lifetime of a variable.
- let mut trivial_builtin = candidates
- .iter()
- .filter(|c| matches!(c.candidate, BuiltinCandidate { has_nested: false }));
- if let Some(_trivial) = trivial_builtin.next() {
- // There should only ever be a single trivial builtin candidate
+ // We prefer `Sized` candidates over everything.
+ let mut sized_candidates =
+ candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ }));
+ if let Some(sized_candidate) = sized_candidates.next() {
+ // There should only ever be a single sized candidate
// as they would otherwise overlap.
- debug_assert_eq!(trivial_builtin.next(), None);
- return Some(BuiltinCandidate { has_nested: false });
+ debug_assert_eq!(sized_candidates.next(), None);
+ // Only prefer the built-in `Sized` candidate if its nested goals are certain.
+ // Otherwise, we may encounter failure later on if inference causes this candidate
+ // to not hold, but a where clause would've applied instead.
+ if sized_candidate.evaluation.must_apply_modulo_regions() {
+ return Some(sized_candidate.candidate.clone());
+ } else {
+ return None;
+ }
}
// Before we consider where-bounds, we have to deduplicate them here and also
@@ -1940,7 +1944,8 @@ fn winnow_candidates(
// Don't use impl candidates which overlap with other candidates.
// This should pretty much only ever happen with malformed impls.
if candidates.iter().all(|c| match c.candidate {
- BuiltinCandidate { has_nested: _ }
+ SizedCandidate { has_nested: _ }
+ | BuiltinCandidate { has_nested: _ }
| TransmutabilityCandidate
| AutoImplCandidate
| ClosureCandidate { .. }
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 89c856f..ba4c849 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -127,15 +127,13 @@ mod prim_bool {}
/// [`Result<String, !>`] which we can unpack like this:
///
/// ```
-/// #![feature(exhaustive_patterns)]
/// use std::str::FromStr;
/// let Ok(s) = String::from_str("hello");
/// ```
///
-/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
-/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
-/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain
-/// enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively
+/// match on [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behavior
+/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`.
///
/// ## Infinite loops
///
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 9144a93..0e1d987 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -38,6 +38,15 @@
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
Highest counter ID seen: c0
+Function name: async_closure::main::{closure#0}
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
+Highest counter ID seen: c0
+
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
Number of files: 1
@@ -47,12 +56,3 @@
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
Highest counter ID seen: c0
-Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
-Number of files: 1
-- file 0 => global file 1
-Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
-Highest counter ID seen: c0
-
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
index 7fbea26..10a8ea1 100644
--- a/tests/coverage/async_closure.coverage
+++ b/tests/coverage/async_closure.coverage
@@ -14,7 +14,7 @@
| async_closure::main::{closure#0}:
| LL| 1| let async_closure = async || {};
------------------
- | async_closure::main::{closure#0}::{closure#1}::<i32>:
+ | async_closure::main::{closure#0}:
| LL| 1| let async_closure = async || {};
------------------
LL| 1| executor::block_on(async_closure());
diff --git a/tests/incremental/user-written-closure-synthetic-closure-conflict.rs b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
new file mode 100644
index 0000000..618604d
--- /dev/null
+++ b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
@@ -0,0 +1,15 @@
+//@ revisions: rpass1 rpass2
+//@ edition: 2024
+
+#![allow(unused)]
+
+fn main() {
+ #[cfg(rpass1)]
+ async || {};
+
+ #[cfg(rpass2)]
+ || {
+ || ();
+ || ();
+ };
+}
diff --git "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 85%
rename from "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
index bd0badd..9070c95 100644
--- "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `foo::{closure#0}::{closure#1}` after built
+// MIR for `foo::{closure#0}::{synthetic#0}` after built
-fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
+fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
index 3c5aec9..e78671f 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.rs
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
@@ -7,7 +7,7 @@ enum Foo {
}
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
fn foo(f: &Foo) {
let x = async move || match f {
Foo::Bar if true => {}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 80%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
index a9e08d2..c5f538e 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built
-fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
similarity index 80%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
index 4452ae7..e295f9b 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built
-fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index cd2e83e..93cc783 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -42,11 +42,11 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
pub fn main() {
block_on(async {
let b = 2i32;
diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs
new file mode 100644
index 0000000..69e322e
--- /dev/null
+++ b/tests/ui/lint/inline-exported.rs
@@ -0,0 +1,30 @@
+//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`,
+//! because `#[inline]` is ignored for such functions.
+
+#![crate_type = "lib"]
+
+#![feature(linkage)]
+#![feature(naked_functions)]
+#![deny(unused_attributes)]
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[no_mangle]
+fn no_mangle() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[export_name = "export_name"]
+fn export_name() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[linkage = "external"]
+fn external_linkage() {}
+
+#[inline]
+fn normal() {}
+
+#[inline]
+#[linkage = "internal"] // not exported
+fn internal_linkage() {}
diff --git a/tests/ui/lint/inline-exported.stderr b/tests/ui/lint/inline-exported.stderr
new file mode 100644
index 0000000..dcf63cc
--- /dev/null
+++ b/tests/ui/lint/inline-exported.stderr
@@ -0,0 +1,31 @@
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:10:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+note: the lint level is defined here
+ --> $DIR/inline-exported.rs:8:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:15:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:20:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/parser/closure-return-syntax.rs b/tests/ui/parser/closure-return-syntax.rs
index c6a08ab..6865d8c 100644
--- a/tests/ui/parser/closure-return-syntax.rs
+++ b/tests/ui/parser/closure-return-syntax.rs
@@ -1,7 +1,21 @@
// Test that we cannot parse a closure with an explicit return type
// unless it uses braces.
-fn main() {
+fn needs_braces_1() {
let x = || -> i32 22;
//~^ ERROR expected `{`, found `22`
}
+
+// Check other delimiters too.
+
+fn needs_braces_2() {
+ let x = || -> (i32, i32) (1, 2);
+ //~^ ERROR expected `{`, found `(`
+}
+
+fn needs_braces_3() {
+ let c = || -> [i32; 2] [1, 2];
+ //~^ ERROR expected `{`, found `[`
+}
+
+fn main() {}
diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr
index aacc31e..763f19c 100644
--- a/tests/ui/parser/closure-return-syntax.stderr
+++ b/tests/ui/parser/closure-return-syntax.stderr
@@ -2,12 +2,40 @@
--> $DIR/closure-return-syntax.rs:5:23
|
LL | let x = || -> i32 22;
- | ^^ expected `{`
+ | --- ^^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
|
-help: you might have meant to write this as part of a block
+help: wrap the expression in curly braces
|
LL | let x = || -> i32 { 22 };
| + +
-error: aborting due to 1 previous error
+error: expected `{`, found `(`
+ --> $DIR/closure-return-syntax.rs:12:34
+ |
+LL | let x = || -> (i32, i32) (1, 2);
+ | ---------- ^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
+ |
+help: wrap the expression in curly braces
+ |
+LL | let x = || -> (i32, i32) { (1, 2) };
+ | + +
+
+error: expected `{`, found `[`
+ --> $DIR/closure-return-syntax.rs:17:32
+ |
+LL | let c = || -> [i32; 2] [1, 2];
+ | -------- ^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
+ |
+help: wrap the expression in curly braces
+ |
+LL | let c = || -> [i32; 2] { [1, 2] };
+ | + +
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index c80a332..6fd6cb4 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -5,19 +5,19 @@
stream: TokenStream [
Ident {
ident: "struct",
- span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
},
Ident {
ident: "S",
- span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
},
],
- span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
+ span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
},
]
#![feature /* 0#0 */(prelude_import)]
@@ -59,7 +59,7 @@
struct S /* 0#0 */;
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
-struct S /* 0#4 */;
+struct S /* 0#5 */;
// OK, not a duplicate definition of `S`
fn main /* 0#0 */() {}
@@ -70,7 +70,7 @@
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
-crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
@@ -83,9 +83,9 @@
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
-#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
-#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
-#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
-#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
+#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
*/
diff --git a/tests/ui/sized/dont-incompletely-prefer-built-in.rs b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
new file mode 100644
index 0000000..f5bf0c8
--- /dev/null
+++ b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+struct W<T: ?Sized>(T);
+
+fn is_sized<T: Sized>(x: *const T) {}
+
+fn dummy<T: ?Sized>() -> *const T { todo!() }
+
+fn non_param_where_bound<T: ?Sized>()
+where
+ W<T>: Sized,
+{
+ let x: *const W<_> = dummy();
+ is_sized::<W<_>>(x);
+ let _: *const W<T> = x;
+}
+
+fn main() {}
diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout
index 21df1fd..12e7a55 100644
--- a/tests/ui/stable-mir-print/async-closure.stdout
+++ b/tests/ui/stable-mir-print/async-closure.stdout
@@ -56,7 +56,7 @@
unreachable;
}
}
-fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
+fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
let mut _0: Poll<()>;
let _3: i32;
let mut _4: &i32;
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index dc8a530..05ae49d 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -98,6 +98,12 @@
LL | trait Baz {}
| ------------ not a function definition
+error: cannot use `#[inline(always)]` with `#[target_feature]`
+ --> $DIR/invalid-attribute.rs:69:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:74:1
|
@@ -163,12 +169,6 @@
LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
-error: cannot use `#[inline(always)]` with `#[target_feature]`
- --> $DIR/invalid-attribute.rs:69:1
- |
-LL | #[inline(always)]
- | ^^^^^^^^^^^^^^^^^
-
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/invalid-attribute.rs:81:1
|
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
new file mode 100644
index 0000000..f4930bf
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+ |
+LL | is_sized::<MaybeSized<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
new file mode 100644
index 0000000..f4930bf
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+ |
+LL | is_sized::<MaybeSized<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.rs b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
new file mode 100644
index 0000000..9dcddea
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
@@ -0,0 +1,19 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MaybeSized<T: ?Sized>(T);
+
+fn is_sized<T: Sized>() -> Box<T> { todo!() }
+
+fn foo<T: ?Sized>()
+where
+ MaybeSized<T>: Sized,
+{
+ is_sized::<MaybeSized<_>>();
+ //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
new file mode 100644
index 0000000..8a8f7b9
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+trait Trait<T>: Sized {}
+impl<T> Trait<T> for T {}
+
+fn is_sized<T: Sized>() {}
+
+fn normal_ref<'a, 'b, T>()
+where
+ &'a u32: Trait<T>,
+{
+ is_sized::<&'b u32>();
+}
+
+struct MyRef<'a, U: ?Sized = ()>(&'a u32, U);
+fn my_ref<'a, 'b, T>()
+where
+ MyRef<'a>: Trait<T>,
+{
+ is_sized::<MyRef<'b>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
new file mode 100644
index 0000000..dd9393f
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+ |
+LL | (MyType<'a, T>,): Sized,
+ | ^^^^^ lifetime mismatch
+ |
+ = note: expected trait `<MyType<'a, T> as Sized>`
+ found trait `<MyType<'static, T> as Sized>`
+note: the lifetime `'a` as defined here...
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | ^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error: lifetime may not live long enough
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | -- lifetime `'a` defined here
+...
+LL | is_sized::<(MyType<'a, T>,)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
new file mode 100644
index 0000000..0586187
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
@@ -0,0 +1,25 @@
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+ |
+LL | (MyType<'a, T>,): Sized,
+ | ^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | ^^
+ = note: but lifetime parameter must outlive the static lifetime
+
+error: lifetime may not live long enough
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | -- lifetime `'a` defined here
+...
+LL | is_sized::<(MyType<'a, T>,)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
new file mode 100644
index 0000000..ae7a6c9
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
@@ -0,0 +1,26 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MyType<'a, T: ?Sized>(&'a (), T);
+
+fn is_sized<T>() {}
+
+fn foo<'a, T: ?Sized>()
+where
+ (MyType<'a, T>,): Sized,
+ //[current]~^ ERROR mismatched types
+ //[next]~^^ ERROR lifetime bound not satisfied
+ MyType<'static, T>: Sized,
+{
+ // Preferring the builtin `Sized` impl of tuples
+ // requires proving `MyType<'a, T>: Sized` which
+ // can only be proven by using the where-clause,
+ // adding an unnecessary `'static` constraint.
+ is_sized::<(MyType<'a, T>,)>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}