1
Fork 0

Auto merge of #136331 - jhpratt:rollup-curo1f4, r=jhpratt

Rollup of 8 pull requests

Successful merges:

 - #135414 (Stabilize `const_black_box`)
 - #136150 (ci: use windows 2025 for i686-mingw)
 - #136258 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 11))
 - #136270 (Remove `NamedVarMap`.)
 - #136278 (add constraint graph to polonius MIR dump)
 - #136287 (LLVM changed the nocapture attribute to captures(none))
 - #136291 (some test suite cleanups)
 - #136296 (float::min/max: mention the non-determinism around signed 0)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-01-31 06:55:04 +00:00
commit 25a16572a3
51 changed files with 287 additions and 188 deletions

View file

@ -1,17 +1,19 @@
use std::io; use std::io;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_middle::mir::pretty::{ use rustc_middle::mir::pretty::{
PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
}; };
use rustc_middle::mir::{Body, ClosureRegionRequirements}; use rustc_middle::mir::{Body, ClosureRegionRequirements, Location};
use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::points::PointIndex;
use rustc_session::config::MirIncludeSpans; use rustc_session::config::MirIncludeSpans;
use crate::borrow_set::BorrowSet; use crate::borrow_set::BorrowSet;
use crate::constraints::OutlivesConstraint; use crate::constraints::OutlivesConstraint;
use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet};
use crate::region_infer::values::LivenessValues;
use crate::type_check::Locations; use crate::type_check::Locations;
use crate::{BorrowckInferCtxt, RegionInferenceContext}; use crate::{BorrowckInferCtxt, RegionInferenceContext};
@ -80,14 +82,27 @@ fn emit_polonius_dump<'tcx>(
body, body,
regioncx, regioncx,
borrow_set, borrow_set,
localized_outlives_constraints, &localized_outlives_constraints,
closure_region_requirements, closure_region_requirements,
out, out,
)?; )?;
writeln!(out, "</code></pre>")?; writeln!(out, "</code></pre>")?;
writeln!(out, "</div>")?; writeln!(out, "</div>")?;
// Section 2: mermaid visualization of the CFG. // Section 2: mermaid visualization of the polonius constraint graph.
writeln!(out, "<div>")?;
writeln!(out, "Polonius constraint graph")?;
writeln!(out, "<pre class='mermaid'>")?;
let edge_count = emit_mermaid_constraint_graph(
borrow_set,
regioncx.liveness_constraints(),
&localized_outlives_constraints,
out,
)?;
writeln!(out, "</pre>")?;
writeln!(out, "</div>")?;
// Section 3: mermaid visualization of the CFG.
writeln!(out, "<div>")?; writeln!(out, "<div>")?;
writeln!(out, "Control-flow graph")?; writeln!(out, "Control-flow graph")?;
writeln!(out, "<pre class='mermaid'>")?; writeln!(out, "<pre class='mermaid'>")?;
@ -95,7 +110,7 @@ fn emit_polonius_dump<'tcx>(
writeln!(out, "</pre>")?; writeln!(out, "</pre>")?;
writeln!(out, "</div>")?; writeln!(out, "</div>")?;
// Section 3: mermaid visualization of the NLL region graph. // Section 4: mermaid visualization of the NLL region graph.
writeln!(out, "<div>")?; writeln!(out, "<div>")?;
writeln!(out, "NLL regions")?; writeln!(out, "NLL regions")?;
writeln!(out, "<pre class='mermaid'>")?; writeln!(out, "<pre class='mermaid'>")?;
@ -103,7 +118,7 @@ fn emit_polonius_dump<'tcx>(
writeln!(out, "</pre>")?; writeln!(out, "</pre>")?;
writeln!(out, "</div>")?; writeln!(out, "</div>")?;
// Section 4: mermaid visualization of the NLL SCC graph. // Section 5: mermaid visualization of the NLL SCC graph.
writeln!(out, "<div>")?; writeln!(out, "<div>")?;
writeln!(out, "NLL SCCs")?; writeln!(out, "NLL SCCs")?;
writeln!(out, "<pre class='mermaid'>")?; writeln!(out, "<pre class='mermaid'>")?;
@ -117,7 +132,11 @@ fn emit_polonius_dump<'tcx>(
"<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>" "<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>"
)?; )?;
writeln!(out, "<script>")?; writeln!(out, "<script>")?;
writeln!(out, "mermaid.initialize({{ startOnLoad: false, maxEdges: 100 }});")?; writeln!(
out,
"mermaid.initialize({{ startOnLoad: false, maxEdges: {} }});",
edge_count.max(100),
)?;
writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?; writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?;
writeln!(out, "</script>")?; writeln!(out, "</script>")?;
writeln!(out, "</body>")?; writeln!(out, "</body>")?;
@ -132,7 +151,7 @@ fn emit_html_mir<'tcx>(
body: &Body<'tcx>, body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>, regioncx: &RegionInferenceContext<'tcx>,
borrow_set: &BorrowSet<'tcx>, borrow_set: &BorrowSet<'tcx>,
localized_outlives_constraints: LocalizedOutlivesConstraintSet, localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
out: &mut dyn io::Write, out: &mut dyn io::Write,
) -> io::Result<()> { ) -> io::Result<()> {
@ -160,7 +179,7 @@ fn emit_html_mir<'tcx>(
regioncx, regioncx,
closure_region_requirements, closure_region_requirements,
borrow_set, borrow_set,
&localized_outlives_constraints, localized_outlives_constraints,
pass_where, pass_where,
out, out,
) )
@ -392,3 +411,76 @@ fn emit_mermaid_nll_sccs<'tcx>(
Ok(()) Ok(())
} }
/// Emits a mermaid flowchart of the polonius localized outlives constraints, with subgraphs per
/// region, and loan introductions.
fn emit_mermaid_constraint_graph<'tcx>(
borrow_set: &BorrowSet<'tcx>,
liveness: &LivenessValues,
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
out: &mut dyn io::Write,
) -> io::Result<usize> {
let location_name = |location: Location| {
// A MIR location looks like `bb5[2]`. As that is not a syntactically valid mermaid node id,
// transform it into `BB5_2`.
format!("BB{}_{}", location.block.index(), location.statement_index)
};
let region_name = |region: RegionVid| format!("'{}", region.index());
let node_name = |region: RegionVid, point: PointIndex| {
let location = liveness.location_from_point(point);
format!("{}_{}", region_name(region), location_name(location))
};
// The mermaid chart type: a top-down flowchart, which supports subgraphs.
writeln!(out, "flowchart TD")?;
// The loans subgraph: a node per loan.
writeln!(out, " subgraph \"Loans\"")?;
for loan_idx in 0..borrow_set.len() {
writeln!(out, " L{loan_idx}")?;
}
writeln!(out, " end\n")?;
// And an edge from that loan node to where it enters the constraint graph.
for (loan_idx, loan) in borrow_set.iter_enumerated() {
writeln!(
out,
" L{} --> {}_{}",
loan_idx.index(),
region_name(loan.region),
location_name(loan.reserve_location),
)?;
}
writeln!(out, "")?;
// The regions subgraphs containing the region/point nodes.
let mut points_per_region: FxIndexMap<RegionVid, FxIndexSet<PointIndex>> =
FxIndexMap::default();
for constraint in &localized_outlives_constraints.outlives {
points_per_region.entry(constraint.source).or_default().insert(constraint.from);
points_per_region.entry(constraint.target).or_default().insert(constraint.to);
}
for (region, points) in points_per_region {
writeln!(out, " subgraph \"{}\"", region_name(region))?;
for point in points {
writeln!(out, " {}", node_name(region, point))?;
}
writeln!(out, " end\n")?;
}
// The constraint graph edges.
for constraint in &localized_outlives_constraints.outlives {
// FIXME: add killed loans and constraint kind as edge labels.
writeln!(
out,
" {} --> {}",
node_name(constraint.source, constraint.from),
node_name(constraint.target, constraint.to),
)?;
}
// Return the number of edges: this is the biggest graph in the dump and its edge count will be
// mermaid's max edge count to support.
let edge_count = borrow_set.len() + localized_outlives_constraints.outlives.len();
Ok(edge_count)
}

View file

@ -3,8 +3,6 @@
// Run-time: // Run-time:
// status: 0 // status: 0
#![feature(const_black_box)]
/* /*
* Code * Code
*/ */

View file

@ -12,13 +12,11 @@ use std::ops::ControlFlow;
use rustc_ast::visit::walk_list; use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{ use rustc_hir::{
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
LifetimeName, Node,
}; };
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
@ -26,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{Ident, Span, sym}; use rustc_span::{Ident, Span, sym};
use tracing::{debug, debug_span, instrument}; use tracing::{debug, debug_span, instrument};
@ -62,33 +60,9 @@ impl ResolvedArg {
} }
} }
/// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to.
///
/// FIXME. This struct gets converted to a `ResolveBoundVars` for
/// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly.
#[derive(Debug, Default)]
struct NamedVarMap {
// maps from every use of a named (not anonymous) bound var to a
// `ResolvedArg` describing how that variable is bound
defs: ItemLocalMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
// - function pointers
// - closures
// - trait refs
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
// List captured variables for each opaque type.
opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
}
struct BoundVarContext<'a, 'tcx> { struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
map: &'a mut NamedVarMap, rbv: &'a mut ResolveBoundVars,
scope: ScopeRef<'a>, scope: ScopeRef<'a>,
} }
@ -267,19 +241,12 @@ pub(crate) fn provide(providers: &mut Providers) {
/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`. /// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
/// You should not read the result of this query directly, but rather use /// You should not read the result of this query directly, but rather use
/// `named_variable_map`, `is_late_bound_map`, etc. /// `named_variable_map`, `late_bound_vars_map`, etc.
#[instrument(level = "debug", skip(tcx))] #[instrument(level = "debug", skip(tcx))]
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars { fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
let mut named_variable_map = NamedVarMap { let mut rbv = ResolveBoundVars::default();
defs: Default::default(), let mut visitor =
late_bound_vars: Default::default(), BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
opaque_captured_lifetimes: Default::default(),
};
let mut visitor = BoundVarContext {
tcx,
map: &mut named_variable_map,
scope: &Scope::Root { opt_parent_item: None },
};
match tcx.hir_owner_node(local_def_id) { match tcx.hir_owner_node(local_def_id) {
hir::OwnerNode::Item(item) => visitor.visit_item(item), hir::OwnerNode::Item(item) => visitor.visit_item(item),
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@ -299,19 +266,10 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
hir::OwnerNode::Synthetic => unreachable!(), hir::OwnerNode::Synthetic => unreachable!(),
} }
let defs = named_variable_map.defs.into_sorted_stable_ord(); debug!(?rbv.defs);
let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord(); debug!(?rbv.late_bound_vars);
let opaque_captured_lifetimes = named_variable_map.opaque_captured_lifetimes; debug!(?rbv.opaque_captured_lifetimes);
let rl = ResolveBoundVars { rbv
defs: SortedMap::from_presorted_elements(defs),
late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
opaque_captured_lifetimes,
};
debug!(?rl.defs);
debug!(?rl.late_bound_vars);
debug!(?rl.opaque_captured_lifetimes);
rl
} }
fn late_arg_as_bound_arg<'tcx>( fn late_arg_as_bound_arg<'tcx>(
@ -404,7 +362,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder { hir_id, .. } => { Scope::Binder { hir_id, .. } => {
// Nested poly trait refs have the binders concatenated // Nested poly trait refs have the binders concatenated
let mut full_binders = let mut full_binders =
self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone(); self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
full_binders.extend(supertrait_bound_vars); full_binders.extend(supertrait_bound_vars);
break (full_binders, BinderScopeType::Concatenating); break (full_binders, BinderScopeType::Concatenating);
} }
@ -646,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let captures = captures.into_inner().into_iter().collect(); let captures = captures.into_inner().into_iter().collect();
debug!(?captures); debug!(?captures);
self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures); self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -848,7 +806,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
hir::TyKind::Ref(lifetime_ref, ref mt) => { hir::TyKind::Ref(lifetime_ref, ref mt) => {
self.visit_lifetime(lifetime_ref); self.visit_lifetime(lifetime_ref);
let scope = Scope::ObjectLifetimeDefault { let scope = Scope::ObjectLifetimeDefault {
lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(), lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
s: self.scope, s: self.scope,
}; };
self.with(scope, |this| this.visit_ty_unambig(mt.ty)); self.with(scope, |this| this.visit_ty_unambig(mt.ty));
@ -966,7 +924,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let bound_vars: Vec<_> = let bound_vars: Vec<_> =
self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect(); self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
let hir_id = self.tcx.local_def_id_to_hir_id(def_id); let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
self.map.late_bound_vars.insert(hir_id.local_id, bound_vars); self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
} }
self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
intravisit::walk_fn_kind(self, fk); intravisit::walk_fn_kind(self, fk);
@ -1140,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
where where
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>), F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{ {
let BoundVarContext { tcx, map, .. } = self; let BoundVarContext { tcx, rbv, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?this.scope.debug_truncated()); let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
{ {
let _enter = span.enter(); let _enter = span.enter();
@ -1150,10 +1108,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} }
fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) { fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) { if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
bug!( bug!(
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
self.map.late_bound_vars[&hir_id.local_id] self.rbv.late_bound_vars[&hir_id.local_id]
) )
} }
} }
@ -1597,9 +1555,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind.descr(param_def_id.to_def_id()) kind.descr(param_def_id.to_def_id())
), ),
}; };
self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
} else { } else {
self.map.defs.insert(hir_id.local_id, def); self.rbv.defs.insert(hir_id.local_id, def);
} }
return; return;
} }
@ -1632,7 +1590,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id())) bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
} }
}); });
self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
return; return;
} }
Scope::Root { .. } => break, Scope::Root { .. } => break,
@ -1725,7 +1683,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} }
}; };
let map = &self.map; let rbv = &self.rbv;
let generics = self.tcx.generics_of(def_id); let generics = self.tcx.generics_of(def_id);
// `type_def_id` points to an item, so there is nothing to inherit generics from. // `type_def_id` points to an item, so there is nothing to inherit generics from.
@ -1744,7 +1702,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// This index can be used with `generic_args` since `parent_count == 0`. // This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize; let index = generics.param_def_id_to_index[&param_def_id] as usize;
generic_args.args.get(index).and_then(|arg| match arg { generic_args.args.get(index).and_then(|arg| match arg {
GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id.local_id).copied(), GenericArg::Lifetime(lt) => rbv.defs.get(&lt.hir_id.local_id).copied(),
_ => None, _ => None,
}) })
} }
@ -2042,7 +2000,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) { fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
debug!(span = ?lifetime_ref.ident.span); debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id.local_id, def); self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
} }
// When we have a return type notation type in a where clause, like // When we have a return type notation type in a where clause, like
@ -2197,7 +2155,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`. // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
// And this is exercised in: // And this is exercised in:
// `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`. // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap(); let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
let existing_bound_vars_saved = existing_bound_vars.clone(); let existing_bound_vars_saved = existing_bound_vars.clone();
existing_bound_vars.extend(bound_vars); existing_bound_vars.extend(bound_vars);
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);

View file

@ -319,7 +319,11 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
case LLVMRustAttributeKind::NoAlias: case LLVMRustAttributeKind::NoAlias:
return Attribute::NoAlias; return Attribute::NoAlias;
case LLVMRustAttributeKind::NoCapture: case LLVMRustAttributeKind::NoCapture:
#if LLVM_VERSION_GE(21, 0)
report_fatal_error("NoCapture doesn't exist in LLVM 21");
#else
return Attribute::NoCapture; return Attribute::NoCapture;
#endif
case LLVMRustAttributeKind::NoCfCheck: case LLVMRustAttributeKind::NoCfCheck:
return Attribute::NoCfCheck; return Attribute::NoCfCheck;
case LLVMRustAttributeKind::NoInline: case LLVMRustAttributeKind::NoInline:
@ -431,6 +435,12 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
extern "C" LLVMAttributeRef extern "C" LLVMAttributeRef
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) { LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
#if LLVM_VERSION_GE(21, 0)
// LLVM 21 replaced the NoCapture attribute with Captures(none).
if (RustAttr == LLVMRustAttributeKind::NoCapture) {
return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
}
#endif
return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr))); return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
} }

View file

@ -45,15 +45,22 @@ pub enum ObjectLifetimeDefault {
Param(DefId), Param(DefId),
} }
/// Maps the id of each lifetime reference to the lifetime decl /// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to. /// that it corresponds to.
#[derive(HashStable, Debug)] #[derive(Debug, Default, HashStable)]
pub struct ResolveBoundVars { pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a // Maps from every use of a named (not anonymous) bound var to a
/// `Region` describing how that region is bound // `ResolvedArg` describing how that variable is bound.
pub defs: SortedMap<ItemLocalId, ResolvedArg>, pub defs: SortedMap<ItemLocalId, ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
// - function pointers
// - closures
// - trait refs
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>, pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
// List captured variables for each opaque type.
pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>, pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
} }

View file

@ -468,9 +468,11 @@ pub fn spin_loop() {
/// // No assumptions can be made about either operand, so the multiplication is not optimized out. /// // No assumptions can be made about either operand, so the multiplication is not optimized out.
/// let y = black_box(5) * black_box(10); /// let y = black_box(5) * black_box(10);
/// ``` /// ```
///
/// During constant evaluation, `black_box` is treated as a no-op.
#[inline] #[inline]
#[stable(feature = "bench_black_box", since = "1.66.0")] #[stable(feature = "bench_black_box", since = "1.66.0")]
#[rustc_const_unstable(feature = "const_black_box", issue = "none")] #[rustc_const_stable(feature = "const_black_box", since = "CURRENT_RUSTC_VERSION")]
pub const fn black_box<T>(dummy: T) -> T { pub const fn black_box<T>(dummy: T) -> T {
crate::intrinsics::black_box(dummy) crate::intrinsics::black_box(dummy)
} }

View file

@ -3725,6 +3725,7 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u
#[rustc_nounwind] #[rustc_nounwind]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_intrinsic_const_stable_indirect]
pub const fn black_box<T>(_dummy: T) -> T { pub const fn black_box<T>(_dummy: T) -> T {
unimplemented!() unimplemented!()
} }

View file

@ -670,7 +670,8 @@ impl f128 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity. /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
/// This also matches the behavior of libms fmax. /// This also matches the behavior of libms fmax. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// #![feature(f128)] /// #![feature(f128)]
@ -696,7 +697,8 @@ impl f128 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids minNum's problems with associativity. /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
/// This also matches the behavior of libms fmin. /// This also matches the behavior of libms fmin. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// #![feature(f128)] /// #![feature(f128)]

View file

@ -662,7 +662,8 @@ impl f16 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity. /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
/// This also matches the behavior of libms fmax. /// This also matches the behavior of libms fmax. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// #![feature(f16)] /// #![feature(f16)]
@ -687,7 +688,8 @@ impl f16 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids minNum's problems with associativity. /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
/// This also matches the behavior of libms fmin. /// This also matches the behavior of libms fmin. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// #![feature(f16)] /// #![feature(f16)]

View file

@ -874,7 +874,8 @@ impl f32 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity. /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
/// This also matches the behavior of libms fmax. /// This also matches the behavior of libms fmax. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// let x = 1.0f32; /// let x = 1.0f32;
@ -895,7 +896,8 @@ impl f32 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids minNum's problems with associativity. /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
/// This also matches the behavior of libms fmin. /// This also matches the behavior of libms fmin. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// let x = 1.0f32; /// let x = 1.0f32;

View file

@ -892,7 +892,8 @@ impl f64 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity. /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
/// This also matches the behavior of libms fmax. /// This also matches the behavior of libms fmax. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// let x = 1.0_f64; /// let x = 1.0_f64;
@ -913,7 +914,8 @@ impl f64 {
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids minNum's problems with associativity. /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
/// This also matches the behavior of libms fmin. /// This also matches the behavior of libms fmin. In particular, if the inputs compare equal
/// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
/// ///
/// ``` /// ```
/// let x = 1.0_f64; /// let x = 1.0_f64;

View file

@ -14,7 +14,6 @@
#![feature(bstr)] #![feature(bstr)]
#![feature(cell_update)] #![feature(cell_update)]
#![feature(clone_to_uninit)] #![feature(clone_to_uninit)]
#![feature(const_black_box)]
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(const_swap_nonoverlapping)] #![feature(const_swap_nonoverlapping)]
#![feature(const_trait_impl)] #![feature(const_trait_impl)]

View file

@ -43,6 +43,10 @@ runners:
os: windows-2022-8core-32gb os: windows-2022-8core-32gb
<<: *base-job <<: *base-job
- &job-windows-25-8c
os: windows-2025-8core-32gb
<<: *base-job
- &job-aarch64-linux - &job-aarch64-linux
# Free some disk space to avoid running out of space during the build. # Free some disk space to avoid running out of space during the build.
free_disk: true free_disk: true
@ -524,7 +528,7 @@ auto:
# We are intentionally allowing an old toolchain on this builder (and that's # We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today). # incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1 NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-8c <<: *job-windows-25-8c
# x86_64-mingw is split into two jobs to run tests in parallel. # x86_64-mingw is split into two jobs to run tests in parallel.
- name: x86_64-mingw-1 - name: x86_64-mingw-1

View file

@ -5,7 +5,7 @@
// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`. // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
// See <https://github.com/rust-lang/rust/issues/111502>. // See <https://github.com/rust-lang/rust/issues/111502>.
// CHECK: i8 @foo(ptr noalias nocapture noundef align 1 dereferenceable(128) %x) // CHECK: i8 @foo(ptr noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x)
#[no_mangle] #[no_mangle]
pub fn foo(x: [u8; 128]) -> u8 { pub fn foo(x: [u8; 128]) -> u8 {
let ptr = core::ptr::addr_of!(x).cast_mut(); let ptr = core::ptr::addr_of!(x).cast_mut();
@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 {
x[0] x[0]
} }
// CHECK: i1 @second(ptr noalias nocapture noundef align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) // CHECK: i1 @second(ptr noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle] #[no_mangle]
pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut(); let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
} }
// If going through a deref (and there are no other mutating accesses), then `readonly` is fine. // If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
// CHECK: i1 @third(ptr noalias nocapture noundef readonly align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) // CHECK: i1 @third(ptr noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle] #[no_mangle]
pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut(); let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();

View file

@ -392,7 +392,7 @@ pub fn call_fiveu16s() {
} }
// CHECK-LABEL: @return_fiveu16s // CHECK-LABEL: @return_fiveu16s
// CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] dereferenceable(10) [[RET_PTR:%.+]]) // CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] {{.*}}dereferenceable(10) [[RET_PTR:%.+]])
#[no_mangle] #[no_mangle]
pub fn return_fiveu16s() -> FiveU16s { pub fn return_fiveu16s() -> FiveU16s {
// powerpc returns this struct via sret pointer, it doesn't use the cast ABI. // powerpc returns this struct via sret pointer, it doesn't use the cast ABI.

View file

@ -135,7 +135,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
#[no_mangle] #[no_mangle]
pub fn notunpin_borrow(_: &NotUnpin) {} pub fn notunpin_borrow(_: &NotUnpin) {}
// CHECK: @indirect_struct(ptr noalias nocapture noundef readonly align 4 dereferenceable(32) %_1) // CHECK: @indirect_struct(ptr noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1)
#[no_mangle] #[no_mangle]
pub fn indirect_struct(_: S) {} pub fn indirect_struct(_: S) {}
@ -198,7 +198,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
x x
} }
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}}) // CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
#[no_mangle] #[no_mangle]
pub fn struct_return() -> S { pub fn struct_return() -> S {
S { _field: [0, 0, 0, 0, 0, 0, 0, 0] } S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }

View file

@ -19,8 +19,10 @@ pub struct ScalarPair {
#[no_mangle] #[no_mangle]
pub fn load(x: &ScalarPair) -> ScalarPair { pub fn load(x: &ScalarPair) -> ScalarPair {
// CHECK-LABEL: @load( // CHECK-LABEL: @load(
// CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0, // CHECK-SAME: sret([32 x i8]) align 16
// CHECK-SAME: align 16 dereferenceable(32) %x // CHECK-SAME: dereferenceable(32) %_0,
// CHECK-SAME: align 16
// CHECK-SAME: dereferenceable(32) %x
// CHECK: [[A:%.*]] = load i32, ptr %x, align 16 // CHECK: [[A:%.*]] = load i32, ptr %x, align 16
// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
// CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16
@ -34,7 +36,8 @@ pub fn load(x: &ScalarPair) -> ScalarPair {
#[no_mangle] #[no_mangle]
pub fn store(x: &mut ScalarPair) { pub fn store(x: &mut ScalarPair) {
// CHECK-LABEL: @store( // CHECK-LABEL: @store(
// CHECK-SAME: align 16 dereferenceable(32) %x // CHECK-SAME: align 16
// CHECK-SAME: dereferenceable(32) %x
// CHECK: store i32 1, ptr %x, align 16 // CHECK: store i32 1, ptr %x, align 16
// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
// CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16
@ -55,8 +58,10 @@ pub fn alloca() {
#[no_mangle] #[no_mangle]
pub fn load_volatile(x: &ScalarPair) -> ScalarPair { pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
// CHECK-LABEL: @load_volatile( // CHECK-LABEL: @load_volatile(
// CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0, // CHECK-SAME: sret([32 x i8]) align 16
// CHECK-SAME: align 16 dereferenceable(32) %x // CHECK-SAME: dereferenceable(32) %_0,
// CHECK-SAME: align 16
// CHECK-SAME: dereferenceable(32) %x
// CHECK: [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16 // CHECK: [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16
// CHECK-NEXT: store %ScalarPair [[LOAD]], ptr %_0, align 16 // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr %_0, align 16
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
@ -66,7 +71,8 @@ pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
#[no_mangle] #[no_mangle]
pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit<i128>, i128) { pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit<i128>, i128) {
// CHECK-LABEL: @transmute( // CHECK-LABEL: @transmute(
// CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0, // CHECK-SAME: sret([32 x i8]) align 16
// CHECK-SAME: dereferenceable(32) %_0,
// CHECK-SAME: i32 noundef %x.0, i128 noundef %x.1 // CHECK-SAME: i32 noundef %x.0, i128 noundef %x.1
// CHECK: store i32 %x.0, ptr %_0, align 16 // CHECK: store i32 %x.0, ptr %_0, align 16
// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %_0, i64 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %_0, i64 16
@ -86,7 +92,8 @@ pub struct Struct {
#[no_mangle] #[no_mangle]
pub fn store_struct(x: &mut Struct) { pub fn store_struct(x: &mut Struct) {
// CHECK-LABEL: @store_struct( // CHECK-LABEL: @store_struct(
// CHECK-SAME: align 16 dereferenceable(32) %x // CHECK-SAME: align 16
// CHECK-SAME: dereferenceable(32) %x
// CHECK: [[TMP:%.*]] = alloca [32 x i8], align 16 // CHECK: [[TMP:%.*]] = alloca [32 x i8], align 16
// CHECK: store i32 1, ptr [[TMP]], align 16 // CHECK: store i32 1, ptr [[TMP]], align 16
// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 4 // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 4

View file

@ -259,11 +259,11 @@ pub struct IntDoubleInt {
c: i32, c: i32,
} }
// CHECK: define void @f_int_double_int_s_arg(ptr noalias nocapture noundef align 8 dereferenceable(24) %a) // CHECK: define void @f_int_double_int_s_arg(ptr noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a)
#[no_mangle] #[no_mangle]
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([24 x i8]) align 8 dereferenceable(24) %_0) // CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0)
#[no_mangle] #[no_mangle]
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt { pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
IntDoubleInt { a: 1, b: 2., c: 3 } IntDoubleInt { a: 1, b: 2., c: 3 }

View file

@ -52,7 +52,7 @@ pub struct BigPacked2 {
#[no_mangle] #[no_mangle]
pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) // CHECK: call void %{{.*}}(ptr{{( captures(none))?}} noalias{{( nocapture)?}} noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// check that calls whose destination is a field of a packed struct // check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an // go through an alloca rather than calling the function with an
@ -64,7 +64,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
#[no_mangle] #[no_mangle]
pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) // CHECK: call void %{{.*}}(ptr{{( captures(none))?}} noalias{{( nocapture)?}} noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// check that calls whose destination is a field of a packed struct // check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an // go through an alloca rather than calling the function with an

View file

@ -263,7 +263,7 @@ pub struct IntDoubleInt {
#[no_mangle] #[no_mangle]
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
// CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 dereferenceable(24) %_0) // CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 {{.*}}dereferenceable(24) %_0)
#[no_mangle] #[no_mangle]
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt { pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
IntDoubleInt { a: 1, b: 2., c: 3 } IntDoubleInt { a: 1, b: 2., c: 3 }

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/104145
//@ check-pass
// Doc links in `Trait`'s methods are resolved because it has a local impl. // Doc links in `Trait`'s methods are resolved because it has a local impl.
//@ aux-build:issue-103463-aux.rs //@ aux-build:issue-103463-aux.rs

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/103463
//@ check-pass
// The `Trait` is not pulled into the crate resulting in doc links in its methods being resolved. // The `Trait` is not pulled into the crate resulting in doc links in its methods being resolved.
//@ aux-build:issue-103463-aux.rs //@ aux-build:issue-103463-aux.rs

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/28480
#![crate_name="foobar"]
//@ aux-build:rustdoc-hidden-sig.rs //@ aux-build:rustdoc-hidden-sig.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
@ -7,7 +10,7 @@
//@ has - '//a' 'u8' //@ has - '//a' 'u8'
extern crate rustdoc_hidden_sig; extern crate rustdoc_hidden_sig;
//@ has issue_28480/struct.Bar.html //@ has foobar/struct.Bar.html
//@ !has - '//a/@title' 'Hidden' //@ !has - '//a/@title' 'Hidden'
//@ has - '//a' 'u8' //@ has - '//a' 'u8'
pub use rustdoc_hidden_sig::Bar; pub use rustdoc_hidden_sig::Bar;

View file

@ -1,27 +1,30 @@
// https://github.com/rust-lang/rust/issues/31948
#![crate_name="foobar"]
//@ aux-build:rustdoc-nonreachable-impls.rs //@ aux-build:rustdoc-nonreachable-impls.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
extern crate rustdoc_nonreachable_impls; extern crate rustdoc_nonreachable_impls;
//@ has issue_31948_1/struct.Wobble.html //@ has foobar/struct.Wobble.html
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
//@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
//@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::hidden::Wobble; pub use rustdoc_nonreachable_impls::hidden::Wobble;
//@ has issue_31948_1/trait.Bark.html //@ has foobar/trait.Bark.html
//@ has - '//h3[@class="code-header"]' 'for Foo' //@ has - '//h3[@class="code-header"]' 'for Foo'
//@ has - '//h3[@class="code-header"]' 'for Wobble' //@ has - '//h3[@class="code-header"]' 'for Wobble'
//@ !has - '//h3[@class="code-header"]' 'for Wibble' //@ !has - '//h3[@class="code-header"]' 'for Wibble'
pub use rustdoc_nonreachable_impls::Bark; pub use rustdoc_nonreachable_impls::Bark;
//@ has issue_31948_1/trait.Woof.html //@ has foobar/trait.Woof.html
//@ has - '//h3[@class="code-header"]' 'for Foo' //@ has - '//h3[@class="code-header"]' 'for Foo'
//@ has - '//h3[@class="code-header"]' 'for Wobble' //@ has - '//h3[@class="code-header"]' 'for Wobble'
//@ !has - '//h3[@class="code-header"]' 'for Wibble' //@ !has - '//h3[@class="code-header"]' 'for Wibble'
pub use rustdoc_nonreachable_impls::Woof; pub use rustdoc_nonreachable_impls::Woof;
//@ !has issue_31948_1/trait.Bar.html //@ !has foobar/trait.Bar.html
//@ !has issue_31948_1/trait.Qux.html //@ !has foobar/trait.Qux.html

View file

@ -1,21 +1,24 @@
// https://github.com/rust-lang/rust/issues/31948
#![crate_name="foobar"]
//@ aux-build:rustdoc-nonreachable-impls.rs //@ aux-build:rustdoc-nonreachable-impls.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
extern crate rustdoc_nonreachable_impls; extern crate rustdoc_nonreachable_impls;
//@ has issue_31948_2/struct.Wobble.html //@ has foobar/struct.Wobble.html
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
//@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
pub use rustdoc_nonreachable_impls::hidden::Wobble; pub use rustdoc_nonreachable_impls::hidden::Wobble;
//@ has issue_31948_2/trait.Qux.html //@ has foobar/trait.Qux.html
//@ has - '//h3[@class="code-header"]' 'for Foo' //@ has - '//h3[@class="code-header"]' 'for Foo'
//@ has - '//h3[@class="code-header"]' 'for Wobble' //@ has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::hidden::Qux; pub use rustdoc_nonreachable_impls::hidden::Qux;
//@ !has issue_31948_2/trait.Bar.html //@ !has foobar/trait.Bar.html
//@ !has issue_31948_2/trait.Woof.html //@ !has foobar/trait.Woof.html
//@ !has issue_31948_2/trait.Bark.html //@ !has foobar/trait.Bark.html

View file

@ -1,29 +1,32 @@
// https://github.com/rust-lang/rust/issues/31948
#![crate_name="foobar"]
//@ aux-build:rustdoc-nonreachable-impls.rs //@ aux-build:rustdoc-nonreachable-impls.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
extern crate rustdoc_nonreachable_impls; extern crate rustdoc_nonreachable_impls;
//@ has issue_31948/struct.Foo.html //@ has foobar/struct.Foo.html
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for' //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
//@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
//@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::Foo; pub use rustdoc_nonreachable_impls::Foo;
//@ has issue_31948/trait.Bark.html //@ has foobar/trait.Bark.html
//@ has - '//h3[@class="code-header"]' 'for Foo' //@ has - '//h3[@class="code-header"]' 'for Foo'
//@ !has - '//h3[@class="code-header"]' 'for Wibble' //@ !has - '//h3[@class="code-header"]' 'for Wibble'
//@ !has - '//h3[@class="code-header"]' 'for Wobble' //@ !has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::Bark; pub use rustdoc_nonreachable_impls::Bark;
//@ has issue_31948/trait.Woof.html //@ has foobar/trait.Woof.html
//@ has - '//h3[@class="code-header"]' 'for Foo' //@ has - '//h3[@class="code-header"]' 'for Foo'
//@ !has - '//h3[@class="code-header"]' 'for Wibble' //@ !has - '//h3[@class="code-header"]' 'for Wibble'
//@ !has - '//h3[@class="code-header"]' 'for Wobble' //@ !has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::Woof; pub use rustdoc_nonreachable_impls::Woof;
//@ !has issue_31948/trait.Bar.html //@ !has foobar/trait.Bar.html
//@ !has issue_31948/trait.Qux.html //@ !has foobar/trait.Qux.html
//@ !has issue_31948/struct.Wibble.html //@ !has foobar/struct.Wibble.html
//@ !has issue_31948/struct.Wobble.html //@ !has foobar/struct.Wobble.html

View file

@ -1,10 +1,13 @@
// https://github.com/rust-lang/rust/issues/32881
#![crate_name="foobar"]
//@ aux-build:rustdoc-trait-object-impl.rs //@ aux-build:rustdoc-trait-object-impl.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
extern crate rustdoc_trait_object_impl; extern crate rustdoc_trait_object_impl;
//@ has issue_32881/trait.Bar.html //@ has foobar/trait.Bar.html
//@ has - '//h3[@class="code-header"]' "impl<'a> dyn Bar" //@ has - '//h3[@class="code-header"]' "impl<'a> dyn Bar"
//@ has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar" //@ has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar"

View file

@ -1,10 +1,13 @@
// https://github.com/rust-lang/rust/issues/33113
#![crate_name="foobar"]
//@ aux-build:issue-33113.rs //@ aux-build:issue-33113.rs
//@ build-aux-docs //@ build-aux-docs
//@ ignore-cross-compile //@ ignore-cross-compile
extern crate bar; extern crate bar;
//@ has issue_33113/trait.Bar.html //@ has foobar/trait.Bar.html
//@ has - '//h3[@class="code-header"]' "for &'a char" //@ has - '//h3[@class="code-header"]' "for &'a char"
//@ has - '//h3[@class="code-header"]' "for Foo" //@ has - '//h3[@class="code-header"]' "for Foo"
pub use bar::Bar; pub use bar::Bar;

View file

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/76736
//@ aux-build:issue-76736-1.rs //@ aux-build:issue-76736-1.rs
//@ aux-build:issue-76736-2.rs //@ aux-build:issue-76736-2.rs

View file

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/76736
//@ aux-build:issue-76736-1.rs //@ aux-build:issue-76736-1.rs
//@ aux-build:issue-76736-2.rs //@ aux-build:issue-76736-2.rs

View file

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/76736
//@ compile-flags: -Zforce-unstable-if-unmarked //@ compile-flags: -Zforce-unstable-if-unmarked
//@ aux-build:issue-76736-1.rs //@ aux-build:issue-76736-1.rs
//@ aux-build:issue-76736-2.rs //@ aux-build:issue-76736-2.rs

View file

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/76736
//@ aux-build:issue-76736-1.rs //@ aux-build:issue-76736-1.rs
//@ aux-build:issue-76736-2.rs //@ aux-build:issue-76736-2.rs

View file

@ -1,3 +1,4 @@
// https://github.com/rust-lang/rust/issues/24183
#![crate_type = "lib"] #![crate_type = "lib"]
#![crate_name = "usr"] #![crate_name = "usr"]

View file

@ -1,12 +1,15 @@
//@ !has issue_32343/struct.Foo.html // https://github.com/rust-lang/rust/issues/32343
//@ has issue_32343/index.html #![crate_name="foobar"]
//@ !has foobar/struct.Foo.html
//@ has foobar/index.html
//@ has - '//code' 'pub use foo::Foo' //@ has - '//code' 'pub use foo::Foo'
//@ !has - '//code/a' 'Foo' //@ !has - '//code/a' 'Foo'
#[doc(no_inline)] #[doc(no_inline)]
pub use foo::Foo; pub use foo::Foo;
//@ !has issue_32343/struct.Bar.html //@ !has foobar/struct.Bar.html
//@ has issue_32343/index.html //@ has foobar/index.html
//@ has - '//code' 'pub use foo::Bar' //@ has - '//code' 'pub use foo::Bar'
//@ has - '//code/a' 'Bar' //@ has - '//code/a' 'Bar'
#[doc(no_inline)] #[doc(no_inline)]
@ -18,6 +21,6 @@ mod foo {
} }
pub mod bar { pub mod bar {
//@ has issue_32343/bar/struct.Bar.html //@ has foobar/bar/struct.Bar.html
pub use ::foo::Bar; pub use ::foo::Bar;
} }

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/28537
#![crate_name="foo"]
#[doc(hidden)] #[doc(hidden)]
pub mod foo { pub mod foo {
pub struct Foo; pub struct Foo;
@ -10,8 +13,8 @@ mod bar {
} }
} }
//@ has issue_28537/struct.Foo.html //@ has foo/struct.Foo.html
pub use foo::Foo; pub use foo::Foo;
//@ has issue_28537/struct.Bar.html //@ has foo/struct.Bar.html
pub use self::bar::Bar; pub use self::bar::Bar;

View file

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/82209
#![crate_name = "foo"] #![crate_name = "foo"]
#![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::broken_intra_doc_links)]
pub enum Foo { pub enum Foo {

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/pull/108459
#![crate_name="foobar"]
#![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::broken_intra_doc_links)]
#![allow(rustdoc::redundant_explicit_links)] #![allow(rustdoc::redundant_explicit_links)]
@ -13,13 +16,13 @@ pub struct MyStruct1;
// the same target but different text // the same target but different text
/// See also [crate::char] and [mod@char] and [prim@char] /// See also [crate::char] and [mod@char] and [prim@char]
//@ has issue_108459/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char' //@ has foobar/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char'
//@ has - '//*[@href="char/index.html"]' 'char' //@ has - '//*[@href="char/index.html"]' 'char'
//@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char' //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
pub struct MyStruct2; pub struct MyStruct2;
/// See also [mod@char] and [prim@char] and [crate::char] /// See also [mod@char] and [prim@char] and [crate::char]
//@ has issue_108459/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char' //@ has foobar/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char'
//@ has - '//*[@href="char/index.html"]' 'char' //@ has - '//*[@href="char/index.html"]' 'char'
//@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char' //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
pub struct MyStruct3; pub struct MyStruct3;
@ -28,11 +31,11 @@ pub struct MyStruct3;
// different targets // different targets
/// See also [char][mod@char] and [char][prim@char] /// See also [char][mod@char] and [char][prim@char]
//@ has issue_108459/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char' //@ has foobar/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char'
//@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char' //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
pub struct MyStruct4; pub struct MyStruct4;
/// See also [char][prim@char] and [char][crate::char] /// See also [char][prim@char] and [char][crate::char]
//@ has issue_108459/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char' //@ has foobar/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char'
//@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char' //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
pub struct MyStruct5; pub struct MyStruct5;

View file

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/66159
#![crate_name="foobar"]
//@ aux-crate:priv:pub_struct=pub-struct.rs //@ aux-crate:priv:pub_struct=pub-struct.rs
//@ compile-flags:-Z unstable-options //@ compile-flags:-Z unstable-options
@ -6,5 +9,5 @@
// Since we don't generate the docs for the auxiliary files, we can't actually // Since we don't generate the docs for the auxiliary files, we can't actually
// verify that the struct is linked correctly. // verify that the struct is linked correctly.
//@ has issue_66159/index.html //@ has foobar/index.html
//! [pub_struct::SomeStruct] //! [pub_struct::SomeStruct]

View file

@ -3,8 +3,6 @@
//! Unfortunately we don't even reach opaque type collection, as we ICE in typeck before that. //! Unfortunately we don't even reach opaque type collection, as we ICE in typeck before that.
//! See #109281 for the original report. //! See #109281 for the original report.
//@ edition:2018 //@ edition:2018
//@ error-pattern: expected generic lifetime parameter, found `'a`
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
use std::future::Future; use std::future::Future;
@ -24,6 +22,7 @@ impl<'x, T: 'x> Trait<'x> for (T,) {
impl Foo<'_> { impl Foo<'_> {
fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> { fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
Box::new((async { () },)) Box::new((async { () },))
//~^ ERROR expected generic lifetime parameter, found `'a`
} }
} }

View file

@ -1,5 +1,5 @@
error[E0792]: expected generic lifetime parameter, found `'a` error[E0792]: expected generic lifetime parameter, found `'a`
--> $DIR/issue-90014-tait2.rs:26:9 --> $DIR/issue-90014-tait2.rs:24:9
| |
LL | type Fut<'a> = impl Future<Output = ()>; LL | type Fut<'a> = impl Future<Output = ()>;
| -- this generic parameter must be used with a generic lifetime parameter | -- this generic parameter must be used with a generic lifetime parameter

View file

@ -1,14 +0,0 @@
//@ check-pass
// https://github.com/rust-lang/rust/issues/129541
#[derive(Clone)]
struct Test {
field: std::borrow::Cow<'static, [Self]>,
}
#[derive(Clone)]
struct Hello {
a: <[Hello] as std::borrow::ToOwned>::Owned,
}
fn main(){}

View file

@ -1,23 +0,0 @@
// Regression test for #129541
//@ check-pass
trait Bound {}
trait Normalize {
type Assoc;
}
impl<T: Bound> Normalize for T {
type Assoc = T;
}
impl<T: Bound> Normalize for [T] {
type Assoc = T;
}
impl Bound for Hello {}
struct Hello {
a: <[Hello] as Normalize>::Assoc,
}
fn main() {}

View file

@ -1,5 +1,6 @@
// Regression test for #129541 // Regression test for #129541
//@ revisions: unique multiple
//@ check-pass //@ check-pass
trait Bound {} trait Bound {}
@ -7,6 +8,10 @@ trait Normalize {
type Assoc; type Assoc;
} }
#[cfg(multiple)]
impl<T: Bound> Normalize for T {
type Assoc = T;
}
impl<T: Bound> Normalize for [T] { impl<T: Bound> Normalize for [T] {
type Assoc = T; type Assoc = T;
} }

View file

@ -1,5 +1,4 @@
// Check that we test WF conditions for fn arguments. Because the // Check that we test WF conditions for fn arguments.
// current code is so goofy, this is only a warning for now.
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![allow(dead_code)] #![allow(dead_code)]

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `Self: Eq` is not satisfied error[E0277]: the trait bound `Self: Eq` is not satisfied
--> $DIR/wf-trait-default-fn-ret.rs:11:22 --> $DIR/wf-trait-default-fn-ret.rs:10:22
| |
LL | fn bar(&self) -> Bar<Self> { LL | fn bar(&self) -> Bar<Self> {
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
| |
note: required by a bound in `Bar` note: required by a bound in `Bar`
--> $DIR/wf-trait-default-fn-ret.rs:8:14 --> $DIR/wf-trait-default-fn-ret.rs:7:14
| |
LL | struct Bar<T:Eq+?Sized> { value: Box<T> } LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
| ^^ required by this bound in `Bar` | ^^ required by this bound in `Bar`