Auto merge of #133360 - compiler-errors:rollup-a2o38tq, r=compiler-errors

Rollup of 8 pull requests

Successful merges:

 - #132090 (Stop being so bail-y in candidate assembly)
 - #132658 (Detect const in pattern with typo)
 - #132911 (Pretty print async fn sugar in opaques and trait bounds)
 - #133102 (aarch64 softfloat target: always pass floats in int registers)
 - #133159 (Don't allow `-Zunstable-options` to take a value )
 - #133208 (generate-copyright: Now generates a library file too.)
 - #133215 (Fix missing submodule in `./x vendor`)
 - #133264 (implement OsString::truncate)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-11-23 04:44:26 +00:00
commit c49a687d63
70 changed files with 1137 additions and 467 deletions

View File

@ -68,6 +68,17 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
/// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family
/// trait, if it is defined.
pub fn async_fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option<DefId> {
let items = self.lang_items();
match kind {
ty::ClosureKind::Fn => items.async_fn_trait(),
ty::ClosureKind::FnMut => items.async_fn_mut_trait(),
ty::ClosureKind::FnOnce => items.async_fn_once_trait(),
}
}
/// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits.
pub fn is_fn_trait(self, id: DefId) -> bool {
self.fn_trait_kind_from_def_id(id).is_some()

View File

@ -16,8 +16,8 @@ use rustc_hir::definitions::{DefKey, DefPathDataName};
use rustc_macros::{Lift, extension};
use rustc_session::Limit;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_span::FileNameDisplayPreference;
use rustc_span::symbol::{Ident, Symbol, kw};
use rustc_span::{FileNameDisplayPreference, sym};
use rustc_type_ir::{Upcast as _, elaborate};
use smallvec::SmallVec;
@ -26,8 +26,8 @@ use super::*;
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
use crate::query::{IntoQueryParam, Providers};
use crate::ty::{
ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TypeFoldable,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitPredicate,
TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
macro_rules! p {
@ -993,10 +993,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
match bound_predicate.skip_binder() {
ty::ClauseKind::Trait(pred) => {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
if tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
match pred.polarity {
ty::PredicatePolarity::Positive => {
has_sized_bound = true;
@ -1007,24 +1005,22 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
self.insert_trait_and_projection(
trait_ref,
pred.polarity,
bound_predicate.rebind(pred),
None,
&mut traits,
&mut fn_traits,
);
}
ty::ClauseKind::Projection(pred) => {
let proj_ref = bound_predicate.rebind(pred);
let trait_ref = proj_ref.required_poly_trait_ref(tcx);
// Projection type entry -- the def-id for naming, and the ty.
let proj_ty = (proj_ref.projection_def_id(), proj_ref.term());
let proj = bound_predicate.rebind(pred);
let trait_ref = proj.map_bound(|proj| TraitPredicate {
trait_ref: proj.projection_term.trait_ref(tcx),
polarity: ty::PredicatePolarity::Positive,
});
self.insert_trait_and_projection(
trait_ref,
ty::PredicatePolarity::Positive,
Some(proj_ty),
Some((proj.projection_def_id(), proj.term())),
&mut traits,
&mut fn_traits,
);
@ -1042,88 +1038,66 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound;
for (fn_once_trait_ref, entry) in fn_traits {
for ((bound_args, is_async), entry) in fn_traits {
write!(self, "{}", if first { "" } else { " + " })?;
write!(self, "{}", if paren_needed { "(" } else { "" })?;
self.wrap_binder(&fn_once_trait_ref, |trait_ref, cx| {
define_scoped_cx!(cx);
// Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = tcx.generics_of(trait_ref.def_id);
let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);
let trait_def_id = if is_async {
tcx.async_fn_trait_kind_to_def_id(entry.kind).expect("expected AsyncFn lang items")
} else {
tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items")
};
match (entry.return_ty, own_args[0].expect_ty()) {
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
// a return type.
(Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
let name = if entry.fn_trait_ref.is_some() {
"Fn"
} else if entry.fn_mut_trait_ref.is_some() {
"FnMut"
} else {
"FnOnce"
};
if let Some(return_ty) = entry.return_ty {
self.wrap_binder(&bound_args, |args, cx| {
define_scoped_cx!(cx);
p!(write("{}", tcx.item_name(trait_def_id)));
p!("(");
p!(write("{}(", name));
for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
if idx > 0 {
p!(", ");
}
p!(print(ty));
for (idx, ty) in args.iter().enumerate() {
if idx > 0 {
p!(", ");
}
p!(")");
if let Some(ty) = return_ty.skip_binder().as_type() {
if !ty.is_unit() {
p!(" -> ", print(return_ty));
}
}
p!(write("{}", if paren_needed { ")" } else { "" }));
first = false;
p!(print(ty));
}
// If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
_ => {
if entry.has_fn_once {
traits
.entry((fn_once_trait_ref, ty::PredicatePolarity::Positive))
.or_default()
.extend(
// Group the return ty with its def id, if we had one.
entry.return_ty.map(|ty| {
(tcx.require_lang_item(LangItem::FnOnceOutput, None), ty)
}),
);
}
if let Some(trait_ref) = entry.fn_mut_trait_ref {
traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default();
}
if let Some(trait_ref) = entry.fn_trait_ref {
traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default();
p!(")");
if let Some(ty) = return_ty.skip_binder().as_type() {
if !ty.is_unit() {
p!(" -> ", print(return_ty));
}
}
}
p!(write("{}", if paren_needed { ")" } else { "" }));
Ok(())
})?;
first = false;
Ok(())
})?;
} else {
// Otherwise, render this like a regular trait.
traits.insert(
bound_args.map_bound(|args| ty::TraitPredicate {
polarity: ty::PredicatePolarity::Positive,
trait_ref: ty::TraitRef::new(tcx, trait_def_id, [Ty::new_tup(tcx, args)]),
}),
FxIndexMap::default(),
);
}
}
// Print the rest of the trait types (that aren't Fn* family of traits)
for ((trait_ref, polarity), assoc_items) in traits {
for (trait_pred, assoc_items) in traits {
write!(self, "{}", if first { "" } else { " + " })?;
self.wrap_binder(&trait_ref, |trait_ref, cx| {
self.wrap_binder(&trait_pred, |trait_pred, cx| {
define_scoped_cx!(cx);
if polarity == ty::PredicatePolarity::Negative {
if trait_pred.polarity == ty::PredicatePolarity::Negative {
p!("!");
}
p!(print(trait_ref.print_only_trait_name()));
p!(print(trait_pred.trait_ref.print_only_trait_name()));
let generics = tcx.generics_of(trait_ref.def_id);
let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);
let generics = tcx.generics_of(trait_pred.def_id());
let own_args = generics.own_args_no_defaults(tcx, trait_pred.trait_ref.args);
if !own_args.is_empty() || !assoc_items.is_empty() {
let mut first = true;
@ -1230,51 +1204,48 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
/// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits.
fn insert_trait_and_projection(
&mut self,
trait_ref: ty::PolyTraitRef<'tcx>,
polarity: ty::PredicatePolarity,
trait_pred: ty::PolyTraitPredicate<'tcx>,
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
traits: &mut FxIndexMap<
(ty::PolyTraitRef<'tcx>, ty::PredicatePolarity),
ty::PolyTraitPredicate<'tcx>,
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
>,
fn_traits: &mut FxIndexMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
fn_traits: &mut FxIndexMap<
(ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>, bool),
OpaqueFnEntry<'tcx>,
>,
) {
let trait_def_id = trait_ref.def_id();
let tcx = self.tcx();
let trait_def_id = trait_pred.def_id();
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
// super-trait ref and record it there.
// We skip negative Fn* bounds since they can't use parenthetical notation anyway.
if polarity == ty::PredicatePolarity::Positive
&& let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait()
let fn_trait_and_async = if let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) {
Some((kind, false))
} else if let Some(kind) = tcx.async_fn_trait_kind_from_def_id(trait_def_id) {
Some((kind, true))
} else {
None
};
if trait_pred.polarity() == ty::PredicatePolarity::Positive
&& let Some((kind, is_async)) = fn_trait_and_async
&& let ty::Tuple(types) = *trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
{
// If we have a FnOnce, then insert it into
if trait_def_id == fn_once_trait {
let entry = fn_traits.entry(trait_ref).or_default();
// Optionally insert the return_ty as well.
if let Some((_, ty)) = proj_ty {
entry.return_ty = Some(ty);
}
entry.has_fn_once = true;
return;
} else if self.tcx().is_lang_item(trait_def_id, LangItem::FnMut) {
let super_trait_ref = elaborate::supertraits(self.tcx(), trait_ref)
.find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
.unwrap();
fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref);
return;
} else if self.tcx().is_lang_item(trait_def_id, LangItem::Fn) {
let super_trait_ref = elaborate::supertraits(self.tcx(), trait_ref)
.find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
.unwrap();
fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref);
return;
let entry = fn_traits
.entry((trait_pred.rebind(types), is_async))
.or_insert_with(|| OpaqueFnEntry { kind, return_ty: None });
if kind.extends(entry.kind) {
entry.kind = kind;
}
if let Some((proj_def_id, proj_ty)) = proj_ty
&& tcx.item_name(proj_def_id) == sym::Output
{
entry.return_ty = Some(proj_ty);
}
return;
}
// Otherwise, just group our traits and projection types.
traits.entry((trait_ref, polarity)).or_default().extend(proj_ty);
traits.entry(trait_pred).or_default().extend(proj_ty);
}
fn pretty_print_inherent_projection(
@ -3189,10 +3160,10 @@ define_print_and_forward_display! {
TraitRefPrintSugared<'tcx> {
if !with_reduced_queries()
&& let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id)
&& cx.tcx().trait_def(self.0.def_id).paren_sugar
&& let ty::Tuple(args) = self.0.args.type_at(1).kind()
{
p!(write("{}", kind.as_str()), "(");
p!(write("{}", cx.tcx().item_name(self.0.def_id)), "(");
for (i, arg) in args.iter().enumerate() {
if i > 0 {
p!(", ");
@ -3415,11 +3386,7 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers { trimmed_def_paths, ..*providers };
}
#[derive(Default)]
pub struct OpaqueFnEntry<'tcx> {
// The trait ref is already stored as a key, so just track if we have it as a real predicate
has_fn_once: bool,
fn_mut_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
kind: ty::ClosureKind,
return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
}

View File

@ -338,6 +338,13 @@ mir_build_unreachable_pattern = unreachable pattern
.unreachable_covered_by_catchall = matches any value
.unreachable_covered_by_one = matches all the relevant values
.unreachable_covered_by_many = multiple earlier patterns match some of the same values
.unreachable_pattern_const_reexport_accessible = there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope
.unreachable_pattern_wanted_const = you might have meant to pattern match against the value of {$is_typo ->
[true] similarly named constant
*[false] constant
} `{$const_name}` instead of introducing a new catch-all binding
.unreachable_pattern_const_inaccessible = there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope
.unreachable_pattern_let_binding = there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings
.suggestion = remove the match arm
mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default

View File

@ -593,6 +593,14 @@ pub(crate) struct UnreachablePattern<'tcx> {
pub(crate) uninhabited_note: Option<()>,
#[label(mir_build_unreachable_covered_by_catchall)]
pub(crate) covered_by_catchall: Option<Span>,
#[subdiagnostic]
pub(crate) wanted_constant: Option<WantedConstant>,
#[note(mir_build_unreachable_pattern_const_reexport_accessible)]
pub(crate) accessible_constant: Option<Span>,
#[note(mir_build_unreachable_pattern_const_inaccessible)]
pub(crate) inaccessible_constant: Option<Span>,
#[note(mir_build_unreachable_pattern_let_binding)]
pub(crate) pattern_let_binding: Option<Span>,
#[label(mir_build_unreachable_covered_by_one)]
pub(crate) covered_by_one: Option<Span>,
#[note(mir_build_unreachable_covered_by_many)]
@ -602,6 +610,20 @@ pub(crate) struct UnreachablePattern<'tcx> {
pub(crate) suggest_remove: Option<Span>,
}
#[derive(Subdiagnostic)]
#[suggestion(
mir_build_unreachable_pattern_wanted_const,
code = "{const_path}",
applicability = "machine-applicable"
)]
pub(crate) struct WantedConstant {
#[primary_span]
pub(crate) span: Span,
pub(crate) is_typo: bool,
pub(crate) const_name: String,
pub(crate) const_path: String,
}
#[derive(Diagnostic)]
#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
pub(crate) struct ConstPatternDependsOnGenericParameter {

View File

@ -7,7 +7,9 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::Reveal;
use rustc_lint::Level;
use rustc_middle::bug;
use rustc_middle::middle::limits::get_limit_size;
use rustc_middle::thir::visit::Visitor;
@ -22,8 +24,10 @@ use rustc_pattern_analysis::rustc::{
use rustc_session::lint::builtin::{
BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::{Span, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::instrument;
use crate::errors::*;
@ -969,6 +973,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
covered_by_one: None,
covered_by_many: None,
covered_by_many_n_more_count: 0,
wanted_constant: None,
accessible_constant: None,
inaccessible_constant: None,
pattern_let_binding: None,
suggest_remove: None,
};
match explanation.covered_by.as_slice() {
@ -991,7 +999,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
});
}
[covering_pat] if pat_is_catchall(covering_pat) => {
lint.covered_by_catchall = Some(covering_pat.data().span);
// A binding pattern that matches all, a single binding name.
let pat = covering_pat.data();
lint.covered_by_catchall = Some(pat.span);
find_fallback_pattern_typo(cx, hir_id, pat, &mut lint);
}
[covering_pat] => {
lint.covered_by_one = Some(covering_pat.data().span);
@ -1024,6 +1035,157 @@ fn report_unreachable_pattern<'p, 'tcx>(
cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint);
}
/// Detect typos that were meant to be a `const` but were interpreted as a new pattern binding.
fn find_fallback_pattern_typo<'tcx>(
cx: &PatCtxt<'_, 'tcx>,
hir_id: HirId,
pat: &Pat<'tcx>,
lint: &mut UnreachablePattern<'_>,
) {
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) {
// This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd
// ICE. At the same time, we don't really need to do all of this if we won't emit anything.
return;
}
if let PatKind::Binding { name, subpattern: None, ty, .. } = pat.kind {
// See if the binding might have been a `const` that was mistyped or out of scope.
let mut accessible = vec![];
let mut accessible_path = vec![];
let mut inaccessible = vec![];
let mut imported = vec![];
let mut imported_spans = vec![];
let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::non_body_analysis());
let parent = cx.tcx.hir().get_parent_item(hir_id);
for item in cx.tcx.hir_crate_items(()).free_items() {
if let DefKind::Use = cx.tcx.def_kind(item.owner_id) {
// Look for consts being re-exported.
let item = cx.tcx.hir().expect_item(item.owner_id.def_id);
let use_name = item.ident.name;
let hir::ItemKind::Use(path, _) = item.kind else {
continue;
};
for res in &path.res {
if let Res::Def(DefKind::Const, id) = res
&& infcx.can_eq(cx.param_env, ty, cx.tcx.type_of(id).instantiate_identity())
{
if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
// The original const is accessible, suggest using it directly.
let item_name = cx.tcx.item_name(*id);
accessible.push(item_name);
accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
} else if cx
.tcx
.visibility(item.owner_id)
.is_accessible_from(parent, cx.tcx)
{
// The const is accessible only through the re-export, point at
// the `use`.
imported.push(use_name);
imported_spans.push(item.ident.span);
}
}
}
}
if let DefKind::Const = cx.tcx.def_kind(item.owner_id)
&& infcx.can_eq(
cx.param_env,
ty,
cx.tcx.type_of(item.owner_id).instantiate_identity(),
)
{
// Look for local consts.
let item_name = cx.tcx.item_name(item.owner_id.into());
let vis = cx.tcx.visibility(item.owner_id);
if vis.is_accessible_from(parent, cx.tcx) {
accessible.push(item_name);
let path = if item_name == name {
// We know that the const wasn't in scope because it has the exact
// same name, so we suggest the full path.
with_no_trimmed_paths!(cx.tcx.def_path_str(item.owner_id))
} else {
// The const is likely just typoed, and nothing else.
cx.tcx.def_path_str(item.owner_id)
};
accessible_path.push(path);
} else if name == item_name {
// The const exists somewhere in this crate, but it can't be imported
// from this pattern's scope. We'll just point at its definition.
inaccessible.push(cx.tcx.def_span(item.owner_id));
}
}
}
if let Some((i, &const_name)) =
accessible.iter().enumerate().find(|(_, &const_name)| const_name == name)
{
// The pattern name is an exact match, so the pattern needed to be imported.
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: false,
const_name: const_name.to_string(),
const_path: accessible_path[i].clone(),
});
} else if let Some(name) = find_best_match_for_name(&accessible, name, None) {
// The pattern name is likely a typo.
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: true,
const_name: name.to_string(),
const_path: name.to_string(),
});
} else if let Some(i) =
imported.iter().enumerate().find(|(_, &const_name)| const_name == name).map(|(i, _)| i)
{
// The const with the exact name wasn't re-exported from an import in this
// crate, we point at the import.
lint.accessible_constant = Some(imported_spans[i]);
} else if let Some(name) = find_best_match_for_name(&imported, name, None) {
// The typoed const wasn't re-exported by an import in this crate, we suggest
// the right name (which will likely require another follow up suggestion).
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: true,
const_path: name.to_string(),
const_name: name.to_string(),
});
} else if !inaccessible.is_empty() {
for span in inaccessible {
// The const with the exact name match isn't accessible, we just point at it.
lint.inaccessible_constant = Some(span);
}
} else {
// Look for local bindings for people that might have gotten confused with how
// `let` and `const` works.
for (_, node) in cx.tcx.hir().parent_iter(hir_id) {
match node {
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(let_stmt), .. }) => {
if let hir::PatKind::Binding(_, _, binding_name, _) = let_stmt.pat.kind {
if name == binding_name.name {
lint.pattern_let_binding = Some(binding_name.span);
}
}
}
hir::Node::Block(hir::Block { stmts, .. }) => {
for stmt in *stmts {
if let hir::StmtKind::Let(let_stmt) = stmt.kind {
if let hir::PatKind::Binding(_, _, binding_name, _) =
let_stmt.pat.kind
{
if name == binding_name.name {
lint.pattern_let_binding = Some(binding_name.span);
}
}
}
}
}
hir::Node::Item(_) => break,
_ => {}
}
}
}
}
}
/// Report unreachable arms, if any.
fn report_arm_reachability<'p, 'tcx>(
cx: &PatCtxt<'p, 'tcx>,

View File

@ -358,7 +358,7 @@ fn build_options<O: Default>(
#[allow(non_upper_case_globals)]
mod desc {
pub(crate) const parse_no_flag: &str = "no value";
pub(crate) const parse_no_value: &str = "no value";
pub(crate) const parse_bool: &str =
"one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`";
pub(crate) const parse_opt_bool: &str = parse_bool;
@ -462,14 +462,18 @@ pub mod parse {
pub(crate) use super::*;
pub(crate) const MAX_THREADS_CAP: usize = 256;
/// This is for boolean options that don't take a value and start with
/// `no-`. This style of option is deprecated.
pub(crate) fn parse_no_flag(slot: &mut bool, v: Option<&str>) -> bool {
/// This is for boolean options that don't take a value, and are true simply
/// by existing on the command-line.
///
/// This style of option is deprecated, and is mainly used by old options
/// beginning with `no-`.
pub(crate) fn parse_no_value(slot: &mut bool, v: Option<&str>) -> bool {
match v {
None => {
*slot = true;
true
}
// Trying to specify a value is always forbidden.
Some(_) => false,
}
}
@ -1609,16 +1613,16 @@ options! {
"perform LLVM link-time optimizations"),
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"metadata to mangle symbol names with"),
no_prepopulate_passes: bool = (false, parse_no_flag, [TRACKED],
no_prepopulate_passes: bool = (false, parse_no_value, [TRACKED],
"give an empty list of passes to the pass manager"),
no_redzone: Option<bool> = (None, parse_opt_bool, [TRACKED],
"disable the use of the redzone"),
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
no_stack_check: bool = (false, parse_no_flag, [UNTRACKED],
no_stack_check: bool = (false, parse_no_value, [UNTRACKED],
"this option is deprecated and does nothing"),
no_vectorize_loops: bool = (false, parse_no_flag, [TRACKED],
no_vectorize_loops: bool = (false, parse_no_value, [TRACKED],
"disable loop vectorization optimization passes"),
no_vectorize_slp: bool = (false, parse_no_flag, [TRACKED],
no_vectorize_slp: bool = (false, parse_no_value, [TRACKED],
"disable LLVM's SLP vectorization pass"),
opt_level: String = ("0".to_string(), parse_string, [TRACKED],
"optimization level (0-3, s, or z; default: 0)"),
@ -1915,25 +1919,25 @@ options! {
"dump facts from NLL analysis into side files (default: no)"),
nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED],
"the directory the NLL facts are dumped into (default: `nll-facts`)"),
no_analysis: bool = (false, parse_no_flag, [UNTRACKED],
no_analysis: bool = (false, parse_no_value, [UNTRACKED],
"parse and expand the source, but run no analysis"),
no_codegen: bool = (false, parse_no_flag, [TRACKED_NO_CRATE_HASH],
no_codegen: bool = (false, parse_no_value, [TRACKED_NO_CRATE_HASH],
"run all passes except codegen; no output"),
no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
no_generate_arange_section: bool = (false, parse_no_value, [TRACKED],
"omit DWARF address ranges that give faster lookups"),
no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED],
"disable the compatibility version of the `implied_bounds_ty` query"),
no_jump_tables: bool = (false, parse_no_flag, [TRACKED],
no_jump_tables: bool = (false, parse_no_value, [TRACKED],
"disable the jump tables and lookup tables that can be generated from a switch case lowering"),
no_leak_check: bool = (false, parse_no_flag, [UNTRACKED],
no_leak_check: bool = (false, parse_no_value, [UNTRACKED],
"disable the 'leak check' for subtyping; unsound, but useful for tests"),
no_link: bool = (false, parse_no_flag, [TRACKED],
no_link: bool = (false, parse_no_value, [TRACKED],
"compile without linking"),
no_parallel_backend: bool = (false, parse_no_flag, [UNTRACKED],
no_parallel_backend: bool = (false, parse_no_value, [UNTRACKED],
"run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
no_profiler_runtime: bool = (false, parse_no_value, [TRACKED],
"prevent automatic injection of the profiler_builtins crate"),
no_trait_vptr: bool = (false, parse_no_flag, [TRACKED],
no_trait_vptr: bool = (false, parse_no_value, [TRACKED],
"disable generation of trait vptr in vtable for upcasting"),
no_unique_section_names: bool = (false, parse_bool, [TRACKED],
"do not use unique names for text and data sections when -Z function-sections is used"),
@ -1991,7 +1995,7 @@ options! {
proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
parse_proc_macro_execution_strategy, [UNTRACKED],
"how to run proc-macro code (default: same-thread)"),
profile_closures: bool = (false, parse_no_flag, [UNTRACKED],
profile_closures: bool = (false, parse_no_value, [UNTRACKED],
"profile size of closures"),
profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
@ -2165,8 +2169,14 @@ written to standard error output)"),
"enable unsound and buggy MIR optimizations (default: no)"),
/// This name is kind of confusing: Most unstable options enable something themselves, while
/// this just allows "normal" options to be feature-gated.
///
/// The main check for `-Zunstable-options` takes place separately from the
/// usual parsing of `-Z` options (see [`crate::config::nightly_options`]),
/// so this boolean value is mostly used for enabling unstable _values_ of
/// stable options. That separate check doesn't handle boolean values, so
/// to avoid an inconsistent state we also forbid them here.
#[rustc_lint_opt_deny_field_access("use `Session::unstable_options` instead of this field")]
unstable_options: bool = (false, parse_bool, [UNTRACKED],
unstable_options: bool = (false, parse_no_value, [UNTRACKED],
"adds unstable command line options to rustc interface (default: no)"),
use_ctors_section: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use legacy .ctors section for initializers rather than .init_array"),

View File

@ -1,5 +1,10 @@
use std::iter;
use rustc_abi::{BackendRepr, Primitive};
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
use crate::abi::{HasDataLayout, TyAbiInterface};
use crate::spec::{HasTargetSpec, Target};
/// Indicates the variant of the AArch64 ABI we are compiling for.
/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
@ -15,7 +20,7 @@ pub(crate) enum AbiKind {
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
let size = arg.layout.size;
@ -27,7 +32,9 @@ where
let valid_unit = match unit.kind {
RegKind::Integer => false,
RegKind::Float => true,
// The softfloat ABI treats floats like integers, so they
// do not get homogeneous aggregate treatment.
RegKind::Float => cx.target_spec().abi != "softfloat",
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
};
@ -35,10 +42,42 @@ where
})
}
fn softfloat_float_abi<Ty>(target: &Target, arg: &mut ArgAbi<'_, Ty>) {
if target.abi != "softfloat" {
return;
}
// Do *not* use the float registers for passing arguments, as that would make LLVM pick the ABI
// and its choice depends on whether `neon` instructions are enabled. Instead, we follow the
// AAPCS "softfloat" ABI, which specifies that floats should be passed as equivalently-sized
// integers. Nominally this only exists for "R" profile chips, but sometimes people don't want
// to use hardfloats even if the hardware supports them, so we do this for all softfloat
// targets.
if let BackendRepr::Scalar(s) = arg.layout.backend_repr
&& let Primitive::Float(f) = s.primitive()
{
arg.cast_to(Reg { kind: RegKind::Integer, size: f.size() });
} else if let BackendRepr::ScalarPair(s1, s2) = arg.layout.backend_repr
&& (matches!(s1.primitive(), Primitive::Float(_))
|| matches!(s2.primitive(), Primitive::Float(_)))
{
// This case can only be reached for the Rust ABI, so we can do whatever we want here as
// long as it does not depend on target features (i.e., as long as we do not use float
// registers). So we pass small things in integer registers and large things via pointer
// indirection. This means we lose the nice "pass it as two arguments" optimization, but we
// currently just have to way to combine a `PassMode::Cast` with that optimization (and we
// need a cast since we want to pass the float as an int).
if arg.layout.size.bits() <= target.pointer_width.into() {
arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size });
} else {
arg.make_indirect();
}
}
}
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !ret.layout.is_sized() {
// Not touching this...
@ -51,6 +90,7 @@ where
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
ret.extend_integer_width_to(32)
}
softfloat_float_abi(cx.target_spec(), ret);
return;
}
if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
@ -69,7 +109,7 @@ where
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !arg.layout.is_sized() {
// Not touching this...
@ -82,6 +122,8 @@ where
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
arg.extend_integer_width_to(32);
}
softfloat_float_abi(cx.target_spec(), arg);
return;
}
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
@ -112,7 +154,7 @@ where
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
if !fn_abi.ret.is_ignore() {
classify_ret(cx, &mut fn_abi.ret, kind);
@ -125,3 +167,13 @@ where
classify_arg(cx, arg, kind);
}
}
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec,
{
for arg in fn_abi.args.iter_mut().chain(iter::once(&mut fn_abi.ret)) {
softfloat_float_abi(cx.target_spec(), arg);
}
}

View File

@ -738,6 +738,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
"x86" => x86::compute_rust_abi_info(cx, self, abi),
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
"loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
"aarch64" => aarch64::compute_rust_abi_info(cx, self),
_ => {}
};

View File

@ -91,14 +91,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else if tcx.is_lang_item(def_id, LangItem::Sized) {
// Sized is never implementable by end-users, it is
// always automatically computed.
// FIXME: Consider moving this check to the top level as it
// may also be useful for predicates other than `Sized`
// Error type cannot possibly implement `Sized` (fixes #123154)
if let Err(e) = obligation.predicate.skip_binder().self_ty().error_reported() {
return Err(SelectionError::Overflow(e.into()));
}
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Unsize) {
@ -230,13 +222,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<(), SelectionError<'tcx>> {
debug!(?stack.obligation);
// An error type will unify with anything. So, avoid
// matching an error type with `ParamCandidate`.
// This helps us avoid spurious errors like issue #121941.
if stack.obligation.predicate.references_error() {
return Ok(());
}
let bounds = stack
.obligation
.param_env
@ -563,19 +548,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Essentially any user-written impl will match with an error type,
// so creating `ImplCandidates` isn't useful. However, we might
// end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`)
// This helps us avoid overflow: see issue #72839
// Since compilation is already guaranteed to fail, this is just
// to try to show the 'nicest' possible errors to the user.
// We don't check for errors in the `ParamEnv` - in practice,
// it seems to cause us to be overly aggressive in deciding
// to give up searching for candidates, leading to spurious errors.
if obligation.predicate.references_error() {
return;
}
let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
self.tcx().for_each_relevant_impl(

View File

@ -2487,10 +2487,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args);
if trait_ref.references_error() {
return Err(());
}
debug!(?impl_trait_header);
let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =

View File

@ -6,8 +6,7 @@ use rustc_index::bit_set::BitSet;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
@ -95,9 +94,6 @@ fn adt_sized_constraint<'tcx>(
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
if let Err(guar) = constraint_ty.error_reported() {
return Some(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
}
// perf hack: if there is a `constraint_ty: Sized` bound, then we know
// that the type is sized and do not need to check it on the impl.

View File

@ -684,19 +684,6 @@ impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
self.skip_binder().projection_term.trait_def_id(cx)
}
/// Get the trait ref required for this projection to be well formed.
/// Note that for generic associated types the predicates of the associated
/// type also need to be checked.
#[inline]
pub fn required_poly_trait_ref(&self, cx: I) -> ty::Binder<I, TraitRef<I>> {
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
// `self.0.trait_ref` is permitted to have escaping regions.
// This is because here `self` has a `Binder` and so does our
// return value, so we are preserving the number of binding
// levels.
self.map_bound(|predicate| predicate.projection_term.trait_ref(cx))
}
pub fn term(&self) -> ty::Binder<I, I::Term> {
self.map_bound(|predicate| predicate.term)
}

View File

@ -550,11 +550,15 @@ impl OsString {
OsStr::from_inner_mut(self.inner.leak())
}
/// Provides plumbing to core `Vec::truncate`.
/// More well behaving alternative to allowing outer types
/// full mutable access to the core `Vec`.
/// Truncate the the `OsString` to the specified length.
///
/// # Panics
/// Panics if `len` does not lie on a valid `OsStr` boundary
/// (as described in [`OsStr::slice_encoded_bytes`]).
#[inline]
pub(crate) fn truncate(&mut self, len: usize) {
#[unstable(feature = "os_string_truncate", issue = "133262")]
pub fn truncate(&mut self, len: usize) {
self.as_os_str().inner.check_public_boundary(len);
self.inner.truncate(len);
}

View File

@ -1023,7 +1023,7 @@ impl Step for PlainSourceTarball {
let mut cmd = command(&builder.initial_cargo);
cmd.arg("vendor").arg("--versioned-dirs");
for p in default_paths_to_vendor(builder) {
for (p, _) in default_paths_to_vendor(builder) {
cmd.arg("--sync").arg(p);
}

View File

@ -211,12 +211,13 @@ impl Step for GenerateCopyright {
fn run(self, builder: &Builder<'_>) -> Self::Output {
let license_metadata = builder.ensure(CollectLicenseMetadata);
// Temporary location, it will be moved to the proper one once it's accurate.
let dest = builder.out.join("COPYRIGHT.html");
let dest_libstd = builder.out.join("COPYRIGHT-library.html");
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
cmd.env("LICENSE_METADATA", &license_metadata);
cmd.env("DEST", &dest);
cmd.env("DEST_LIBSTD", &dest_libstd);
cmd.env("OUT_DIR", &builder.out);
cmd.env("CARGO", &builder.initial_cargo);
cmd.run(builder);

View File

@ -4,24 +4,26 @@ use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::utils::exec::command;
/// List of default paths used for vendoring for `x vendor` and dist tarballs.
pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<PathBuf> {
let mut paths = vec![];
for p in [
"src/tools/cargo/Cargo.toml",
"src/tools/rust-analyzer/Cargo.toml",
"compiler/rustc_codegen_cranelift/Cargo.toml",
"compiler/rustc_codegen_gcc/Cargo.toml",
"library/Cargo.toml",
"src/bootstrap/Cargo.toml",
"src/tools/rustbook/Cargo.toml",
"src/tools/rustc-perf/Cargo.toml",
"src/tools/opt-dist/Cargo.toml",
] {
paths.push(builder.src.join(p));
}
paths
/// Returns the cargo workspaces to vendor for `x vendor` and dist tarballs.
///
/// Returns a `Vec` of `(path_to_manifest, submodules_required)` where
/// `path_to_manifest` is the cargo workspace, and `submodules_required` is
/// the set of submodules that must be available.
pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> {
[
("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]),
("src/tools/rust-analyzer/Cargo.toml", vec![]),
("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
("library/Cargo.toml", vec![]),
("src/bootstrap/Cargo.toml", vec![]),
("src/tools/rustbook/Cargo.toml", SUBMODULES_FOR_RUSTBOOK.into()),
("src/tools/rustc-perf/Cargo.toml", vec!["src/tools/rustc-perf"]),
("src/tools/opt-dist/Cargo.toml", vec![]),
]
.into_iter()
.map(|(path, submodules)| (builder.src.join(path), submodules))
.collect()
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@ -56,13 +58,16 @@ impl Step for Vendor {
cmd.arg("--versioned-dirs");
}
let to_vendor = default_paths_to_vendor(builder);
// These submodules must be present for `x vendor` to work.
for submodule in SUBMODULES_FOR_RUSTBOOK.iter().chain(["src/tools/cargo"].iter()) {
builder.build.require_submodule(submodule, None);
for (_, submodules) in &to_vendor {
for submodule in submodules {
builder.build.require_submodule(submodule, None);
}
}
// Sync these paths by default.
for p in default_paths_to_vendor(builder) {
for (p, _) in &to_vendor {
cmd.arg("--sync").arg(p);
}

View File

@ -45,21 +45,20 @@ pub struct PackageMetadata {
/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data.
///
/// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can
/// This will involve running `cargo vendor` into `vendor_path` so we can
/// grab the license files.
///
/// Any dependency with a path beginning with `root_path` is ignored, as we
/// assume `reuse` has covered it already.
pub fn get_metadata_and_notices(
cargo: &Path,
dest: &Path,
vendor_path: &Path,
root_path: &Path,
manifest_paths: &[&Path],
) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
let mut output = get_metadata(cargo, root_path, manifest_paths)?;
// Now do a cargo-vendor and grab everything
let vendor_path = dest.join("vendor");
println!("Vendoring deps into {}...", vendor_path.display());
run_cargo_vendor(cargo, &vendor_path, manifest_paths)?;

View File

@ -6,13 +6,6 @@ use rinja::Template;
mod cargo_metadata;
#[derive(Template)]
#[template(path = "COPYRIGHT.html")]
struct CopyrightTemplate {
in_tree: Node,
dependencies: BTreeMap<cargo_metadata::Package, cargo_metadata::PackageMetadata>,
}
/// The entry point to the binary.
///
/// You should probably let `bootstrap` execute this program instead of running it directly.
@ -20,49 +13,89 @@ struct CopyrightTemplate {
/// Run `x.py run generate-copyright`
fn main() -> Result<(), Error> {
let dest_file = env_path("DEST")?;
let libstd_dest_file = env_path("DEST_LIBSTD")?;
let out_dir = env_path("OUT_DIR")?;
let cargo = env_path("CARGO")?;
let license_metadata = env_path("LICENSE_METADATA")?;
let root_path = std::path::absolute(".")?;
// Scan Cargo dependencies
let mut collected_cargo_metadata =
cargo_metadata::get_metadata_and_notices(&cargo, &out_dir.join("vendor"), &root_path, &[
Path::new("./Cargo.toml"),
Path::new("./src/tools/cargo/Cargo.toml"),
Path::new("./library/Cargo.toml"),
])?;
let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
&cargo,
&out_dir.join("library-vendor"),
&root_path,
&[Path::new("./library/Cargo.toml")],
)?;
for (key, value) in collected_cargo_metadata.iter_mut() {
value.is_in_libstd = Some(library_collected_cargo_metadata.contains_key(key));
}
// Load JSON output by reuse
let collected_tree_metadata: Metadata =
serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
let root_path = std::path::absolute(".")?;
let workspace_paths = [
Path::new("./Cargo.toml"),
Path::new("./src/tools/cargo/Cargo.toml"),
Path::new("./library/Cargo.toml"),
];
let mut collected_cargo_metadata =
cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?;
let stdlib_set =
cargo_metadata::get_metadata(&cargo, &root_path, &[Path::new("./library/std/Cargo.toml")])?;
for (key, value) in collected_cargo_metadata.iter_mut() {
value.is_in_libstd = Some(stdlib_set.contains_key(key));
}
// Find libstd sub-set
let library_collected_tree_metadata = Metadata {
files: collected_tree_metadata
.files
.trim_clone(&Path::new("./library"), &Path::new("."))
.unwrap(),
};
// Output main file
let template = CopyrightTemplate {
in_tree: collected_tree_metadata.files,
dependencies: collected_cargo_metadata,
};
let output = template.render()?;
std::fs::write(&dest_file, output)?;
// Output libstd subset file
let template = LibraryCopyrightTemplate {
in_tree: library_collected_tree_metadata.files,
dependencies: library_collected_cargo_metadata,
};
let output = template.render()?;
std::fs::write(&libstd_dest_file, output)?;
Ok(())
}
/// The HTML template for the toolchain copyright file
#[derive(Template)]
#[template(path = "COPYRIGHT.html")]
struct CopyrightTemplate {
in_tree: Node,
dependencies: BTreeMap<cargo_metadata::Package, cargo_metadata::PackageMetadata>,
}
/// The HTML template for the library copyright file
#[derive(Template)]
#[template(path = "COPYRIGHT-library.html")]
struct LibraryCopyrightTemplate {
in_tree: Node,
dependencies: BTreeMap<cargo_metadata::Package, cargo_metadata::PackageMetadata>,
}
/// Describes a tree of metadata for our filesystem tree
#[derive(serde::Deserialize)]
///
/// Must match the JSON emitted by the `CollectLicenseMetadata` bootstrap tool.
#[derive(serde::Deserialize, Clone, Debug, PartialEq, Eq)]
struct Metadata {
files: Node,
}
/// Describes one node in our metadata tree
#[derive(serde::Deserialize, rinja::Template)]
#[derive(serde::Deserialize, rinja::Template, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case", tag = "type")]
#[template(path = "Node.html")]
pub(crate) enum Node {
@ -72,8 +105,74 @@ pub(crate) enum Node {
Group { files: Vec<String>, directories: Vec<String>, license: License },
}
impl Node {
/// Clone, this node, but only if the path to the item is within the match path
fn trim_clone(&self, match_path: &Path, parent_path: &Path) -> Option<Node> {
match self {
Node::Root { children } => {
let mut filtered_children = Vec::new();
for node in children {
if let Some(child_node) = node.trim_clone(match_path, parent_path) {
filtered_children.push(child_node);
}
}
if filtered_children.is_empty() {
None
} else {
Some(Node::Root { children: filtered_children })
}
}
Node::Directory { name, children, license } => {
let child_name = parent_path.join(name);
if !(child_name.starts_with(match_path) || match_path.starts_with(&child_name)) {
return None;
}
let mut filtered_children = Vec::new();
for node in children {
if let Some(child_node) = node.trim_clone(match_path, &child_name) {
filtered_children.push(child_node);
}
}
Some(Node::Directory {
name: name.clone(),
children: filtered_children,
license: license.clone(),
})
}
Node::File { name, license } => {
let child_name = parent_path.join(name);
if !(child_name.starts_with(match_path) || match_path.starts_with(&child_name)) {
return None;
}
Some(Node::File { name: name.clone(), license: license.clone() })
}
Node::Group { files, directories, license } => {
let mut filtered_child_files = Vec::new();
for child in files {
let child_name = parent_path.join(child);
if child_name.starts_with(match_path) || match_path.starts_with(&child_name) {
filtered_child_files.push(child.clone());
}
}
let mut filtered_child_dirs = Vec::new();
for child in directories {
let child_name = parent_path.join(child);
if child_name.starts_with(match_path) || match_path.starts_with(&child_name) {
filtered_child_dirs.push(child.clone());
}
}
Some(Node::Group {
files: filtered_child_files,
directories: filtered_child_dirs,
license: license.clone(),
})
}
}
}
}
/// A License has an SPDX license name and a list of copyright holders.
#[derive(serde::Deserialize)]
#[derive(serde::Deserialize, Clone, Debug, PartialEq, Eq)]
struct License {
spdx: String,
copyright: Vec<String>,

View File

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Copyright notices for The Rust Standard Library</title>
</head>
<body>
<h1>Copyright notices for The Rust Standard Library</h1>
<p>This file describes the copyright and licensing information for the Rust
Standard Library source code within The Rust Project git tree, and the
third-party dependencies used when building the Rust Standard Library.</p>
<h2>Table of Contents</h2>
<ul>
<li><a href="#in-tree-files">In-tree files</a></li>
<li><a href="#out-of-tree-dependencies">Out-of-tree dependencies</a></li>
</ul>
<h2 id="in-tree-files">In-tree files</h2>
<p>The following licenses cover the in-tree source files that were used in this
release:</p>
{{ in_tree|safe }}
<h2 id="out-of-tree-dependencies">Out-of-tree dependencies</h2>
<p>The following licenses cover the out-of-tree crates that were used in the
Rust Standard Library in this release:</p>
{% for (key, value) in dependencies %}
<h3>📦 {{key.name}}-{{key.version}}</h3>
<p><b>URL:</b> <a href="https://crates.io/crates/{{ key.name }}/{{ key.version }}">https://crates.io/crates/{{ key.name }}/{{ key.version }}</a></p>
<p><b>Authors:</b> {{ value.authors|join(", ") }}</p>
<p><b>License:</b> {{ value.license }}</p>
{% let len = value.notices.len() %}
{% if len > 0 %}
<p><b>Notices:</b>
{% for (notice_name, notice_text) in value.notices %}
<details>
<summary><code>{{ notice_name }}</code></summary>
<pre>
{{ notice_text }}
</pre>
</details>
{% endfor %}
</p>
{% endif %}
{% endfor %}
</body>
</html>

View File

@ -0,0 +1,48 @@
//@ compile-flags: --target aarch64-unknown-none-softfloat -Zmerge-functions=disabled
//@ needs-llvm-components: aarch64
#![crate_type = "lib"]
#![feature(no_core, lang_items)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for f32 {}
impl Copy for f64 {}
// CHECK: i64 @pass_f64_C(i64 {{[^,]*}})
#[no_mangle]
extern "C" fn pass_f64_C(x: f64) -> f64 {
x
}
// CHECK: i64 @pass_f32_pair_C(i64 {{[^,]*}})
#[no_mangle]
extern "C" fn pass_f32_pair_C(x: (f32, f32)) -> (f32, f32) {
x
}
// CHECK: [2 x i64] @pass_f64_pair_C([2 x i64] {{[^,]*}})
#[no_mangle]
extern "C" fn pass_f64_pair_C(x: (f64, f64)) -> (f64, f64) {
x
}
// CHECK: i64 @pass_f64_Rust(i64 {{[^,]*}})
#[no_mangle]
fn pass_f64_Rust(x: f64) -> f64 {
x
}
// CHECK: i64 @pass_f32_pair_Rust(i64 {{[^,]*}})
#[no_mangle]
fn pass_f32_pair_Rust(x: (f32, f32)) -> (f32, f32) {
x
}
// CHECK: void @pass_f64_pair_Rust(ptr {{[^,]*}}, ptr {{[^,]*}})
#[no_mangle]
fn pass_f64_pair_Rust(x: (f64, f64)) -> (f64, f64) {
x
}

View File

@ -1,17 +0,0 @@
//@ known-bug: #124350
struct Node<const D: usize> {}
impl Node<D>
where
SmallVec<{ D * 2 }>:,
{
fn new() -> Self {
let mut node = Node::new();
(&a, 0)();
node
}
}
struct SmallVec<T1, T2> {}

View File

@ -1,26 +0,0 @@
//@ known-bug: rust-lang/rust#125758
#![feature(impl_trait_in_assoc_type)]
trait Trait: Sized {
type Assoc2;
}
impl Trait for Bar {
type Assoc2 = impl std::fmt::Debug;
}
struct Foo {
field: <Bar as Trait>::Assoc2,
}
enum Bar {
C = 42,
D = 99,
}
static BAR: u8 = 42;
static FOO2: (&Foo, &<Bar as Trait>::Assoc2) =
unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) };
fn main() {}

View File

@ -1,17 +0,0 @@
//@ known-bug: #127351
#![feature(lazy_type_alias)]
#![allow(incomplete_features)]
struct Outer0<'a, T>(ExplicitTypeOutlives<'a, T>);
type ExplicitTypeOutlives<'a, T: 'a> = (&'a (), T);
pub struct Warns {
_significant_drop: ExplicitTypeOutlives,
field: String,
}
pub fn test(w: Warns) {
_ = || drop(w.field);
}
fn main() {}

View File

@ -1,18 +0,0 @@
//@ known-bug: #127353
#![feature(type_alias_impl_trait)]
trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>;
fn f<'a>() -> Alias<'a, ()> {}
pub enum UninhabitedVariants {
Tuple(Alias),
}
struct A;
fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
match x {}
}
fn main() {}

View File

@ -1,11 +0,0 @@
//@ known-bug: #127742
struct Vtable(dyn Cap); // missing lifetime
trait Cap<'a> {}
union Transmute {
t: u64, // ICEs with u64, u128, or usize. Correctly errors with u32.
u: &'static Vtable,
}
const G: &'static Vtable = unsafe { Transmute { t: 1 }.u };

View File

@ -6,7 +6,7 @@ struct Vtable(dyn Cap);
trait Cap<'a> {}
union Transmute {
t: u64,
t: u128,
u: &'static Vtable,
}

View File

@ -1,8 +1,8 @@
error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn<()>` is not satisfied
error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn()` is not satisfied
--> $DIR/fn-exception-target-features.rs:16:10
|
LL | test(target_feature);
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
| |
| required by a bound introduced by this call
|

View File

@ -1,8 +1,8 @@
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn<()>` is not satisfied
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn()` is not satisfied
--> $DIR/fn-exception.rs:19:10
|
LL | test(unsafety);
| ---- ^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
| ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
| |
| required by a bound introduced by this call
|
@ -12,11 +12,11 @@ note: required by a bound in `test`
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn<()>` is not satisfied
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
--> $DIR/fn-exception.rs:20:10
|
LL | test(abi);
| ---- ^^^ the trait `AsyncFn<()>` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
| ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
| |
| required by a bound introduced by this call
|

View File

@ -0,0 +1,14 @@
//@ edition: 2021
#![feature(async_closure)]
use std::ops::AsyncFnMut;
fn produce() -> impl AsyncFnMut() -> &'static str {
async || ""
}
fn main() {
let x: i32 = produce();
//~^ ERROR mismatched types
}

View File

@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/pretty-async-fn-opaque.rs:12:18
|
LL | fn produce() -> impl AsyncFnMut() -> &'static str {
| --------------------------------- the found opaque type
...
LL | let x: i32 = produce();
| --- ^^^^^^^^^ expected `i32`, found opaque type
| |
| expected due to this
|
= note: expected type `i32`
found opaque type `impl AsyncFnMut() -> &'static str`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,7 +1,7 @@
//@ revisions: ascii unicode
//@ compile-flags: --color=always
//@[ascii] compile-flags: --error-format=human
//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode
//@ ignore-windows
fn main() {
let _ = match true {

View File

@ -0,0 +1,18 @@
// regression test for #124350
struct Node<const D: usize> {}
impl<const D: usize> Node<D>
where
SmallVec<{ D * 2 }>:,
//~^ ERROR generic parameters may not be used in const operations
//~| ERROR constant provided when a type was expected
{
fn new() -> Self {
Node::new()
}
}
struct SmallVec<T1>(T1);
fn main() {}

View File

@ -0,0 +1,18 @@
error: generic parameters may not be used in const operations
--> $DIR/bad-multiply.rs:7:16
|
LL | SmallVec<{ D * 2 }>:,
| ^ cannot perform const operation using `D`
|
= help: const parameters may only be used as standalone arguments, i.e. `D`
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
error[E0747]: constant provided when a type was expected
--> $DIR/bad-multiply.rs:7:14
|
LL | SmallVec<{ D * 2 }>:,
| ^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0747`.

View File

@ -20,5 +20,4 @@ pub fn remove_key<K, S: SubsetExcept<K>>() -> S {
fn main() {
let map: KeyHolder<0> = remove_key::<_, _>();
//~^ ERROR: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied
}

View File

@ -14,26 +14,6 @@ LL | impl<K> ContainsKey<K> for KeyHolder<K> {}
| |
| help: consider changing this type parameter to a const parameter: `const K: u8`
error[E0277]: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied
--> $DIR/kind_mismatch.rs:22:45
|
LL | let map: KeyHolder<0> = remove_key::<_, _>();
| ^ the trait `ContainsKey<0>` is not implemented for `KeyHolder<0>`
|
note: required for `KeyHolder<0>` to implement `SubsetExcept<_>`
--> $DIR/kind_mismatch.rs:15:28
|
LL | impl<P, T: ContainsKey<0>> SubsetExcept<P> for T {}
| -------------- ^^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `remove_key`
--> $DIR/kind_mismatch.rs:17:25
|
LL | pub fn remove_key<K, S: SubsetExcept<K>>() -> S {
| ^^^^^^^^^^^^^^^ required by this bound in `remove_key`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0747.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0747`.

View File

@ -1,6 +1,6 @@
//@ revisions: ascii unicode
//@[ascii] compile-flags: --diagnostic-width=40
//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=40
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
trait Future {
type Error;

View File

@ -1,6 +1,6 @@
//@ revisions: ascii unicode
//@[ascii] compile-flags: --diagnostic-width=20
//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=20
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=20
// This test checks that `-Z output-width` effects the human error output by restricting it to an
// arbitrarily low value so that the effect is visible.

View File

@ -1,6 +1,6 @@
//@ revisions: ascii unicode
//@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
//@[unicode] compile-flags: -Zunstable-options=yes --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
//@[unicode] compile-flags: -Zunstable-options --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
mod a {

View File

@ -1,5 +1,5 @@
//@ revisions: ascii unicode
//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode
// ignore-tidy-linelength
fn main() {

View File

@ -1,5 +1,5 @@
//@ revisions: ascii unicode
//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode
// ignore-tidy-linelength
fn main() {

View File

@ -1,4 +1,4 @@
//@ compile-flags: -Zunstable-options=yes --error-format=human-unicode --color=always
//@ compile-flags: -Zunstable-options --error-format=human-unicode --color=always
//@ edition:2018
//@ only-linux

View File

@ -16,6 +16,8 @@ struct Holder<B> {
fn main() {
Holder {
inner: Box::new(()), //~ ERROR: the trait `Provider` cannot be made into an object
inner: Box::new(()),
//~^ ERROR: the trait `Provider` cannot be made into an object
//~| ERROR: the trait `Provider` cannot be made into an object
};
}

View File

@ -80,7 +80,24 @@ LL | type A<'a>;
= help: consider moving `A` to another trait
= help: only type `()` implements the trait, consider using it directly instead
error: aborting due to 5 previous errors
error[E0038]: the trait `Provider` cannot be made into an object
--> $DIR/issue-71176.rs:19:16
|
LL | inner: Box::new(()),
| ^^^^^^^^^^^^ `Provider` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-71176.rs:2:10
|
LL | trait Provider {
| -------- this trait cannot be made into an object...
LL | type A<'a>;
| ^ ...because it contains the generic associated type `A`
= help: consider moving `A` to another trait
= help: only type `()` implements the trait, consider using it directly instead
= note: required for the cast from `Box<()>` to `Box<(dyn Provider<A<'_> = _> + 'static), {type error}>`
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.

View File

@ -74,7 +74,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/opaque-used-in-extraneous-argument.rs:20:5
|
LL | open_parent(&old_path)
| ^^^^^^^^^^^ --------- unexpected argument of type `&impl FnOnce<{type error}, Output = {type error}> + Fn<{type error}> + 'static`
| ^^^^^^^^^^^ --------- unexpected argument of type `&impl Fn<{type error}> + FnOnce<{type error}, Output = {type error}> + 'static`
|
note: function defined here
--> $DIR/opaque-used-in-extraneous-argument.rs:12:4

View File

@ -1,3 +1,5 @@
//@ normalize-stderr-test: "\d+ bits" -> "$$BITS bits"
// Regression test for issue #124031
// Checks that we don't ICE when the tail
// of an ADT has a type error
@ -16,5 +18,6 @@ struct Other {
fn main() {
unsafe {
std::mem::transmute::<Option<()>, Option<&Other>>(None);
//~^ ERROR cannot transmute between types of different sizes
}
}

View File

@ -1,5 +1,5 @@
error[E0046]: not all trait items implemented, missing: `RefTarget`
--> $DIR/ice-type-error-in-tail-124031.rs:9:1
--> $DIR/ice-type-error-in-tail-124031.rs:11:1
|
LL | type RefTarget;
| -------------- `RefTarget` from trait
@ -7,6 +7,16 @@ LL | type RefTarget;
LL | impl Trait for () {}
| ^^^^^^^^^^^^^^^^^ missing `RefTarget` in implementation
error: aborting due to 1 previous error
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/ice-type-error-in-tail-124031.rs:20:9
|
LL | std::mem::transmute::<Option<()>, Option<&Other>>(None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: `Option<()>` ($BITS bits)
= note: target type: `Option<&Other>` ($BITS bits)
For more information about this error, try `rustc --explain E0046`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0046, E0512.
For more information about an error, try `rustc --explain E0046`.

View File

@ -0,0 +1,18 @@
// regression test for #127351
#![feature(lazy_type_alias)]
//~^ WARN the feature `lazy_type_alias` is incomplete
type ExplicitTypeOutlives<T> = T;
pub struct Warns {
_significant_drop: ExplicitTypeOutlives,
//~^ ERROR missing generics for type alias `ExplicitTypeOutlives`
field: String,
}
pub fn test(w: Warns) {
let _ = || drop(w.field);
}
fn main() {}

View File

@ -0,0 +1,28 @@
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bad-lazy-type-alias.rs:3:12
|
LL | #![feature(lazy_type_alias)]
| ^^^^^^^^^^^^^^^
|
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0107]: missing generics for type alias `ExplicitTypeOutlives`
--> $DIR/bad-lazy-type-alias.rs:9:24
|
LL | _significant_drop: ExplicitTypeOutlives,
| ^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument
|
note: type alias defined here, with 1 generic parameter: `T`
--> $DIR/bad-lazy-type-alias.rs:6:6
|
LL | type ExplicitTypeOutlives<T> = T;
| ^^^^^^^^^^^^^^^^^^^^ -
help: add missing generic argument
|
LL | _significant_drop: ExplicitTypeOutlives<T>,
| +++
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0107`.

View File

@ -11,5 +11,4 @@ impl Lt<'missing> for () { //~ ERROR undeclared lifetime
fn main() {
let _: <() as Lt<'_>>::T = &();
//~^ ERROR the trait bound `(): Lt<'_>` is not satisfied
}

View File

@ -21,13 +21,6 @@ help: consider introducing lifetime `'missing` here
LL | impl<'missing> Lt<'missing> for () {
| ++++++++++
error[E0277]: the trait bound `(): Lt<'_>` is not satisfied
--> $DIR/region-error-ice-109072.rs:13:13
|
LL | let _: <() as Lt<'_>>::T = &();
| ^^ the trait `Lt<'_>` is not implemented for `()`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0261, E0277.
For more information about an error, try `rustc --explain E0261`.
For more information about this error, try `rustc --explain E0261`.

View File

@ -0,0 +1,45 @@
#![deny(unreachable_patterns)] //~ NOTE the lint level is defined here
#![allow(non_snake_case, non_upper_case_globals)]
mod x {
pub use std::env::consts::ARCH;
const X: i32 = 0; //~ NOTE there is a constant of the same name
}
fn main() {
let input: i32 = 42;
const god: i32 = 1;
const GOOD: i32 = 1;
const BAD: i32 = 2;
let name: i32 = 42; //~ NOTE there is a binding of the same name
match input {
X => {} //~ NOTE matches any value
_ => {} //~ ERROR unreachable pattern
//~^ NOTE no value can reach this
}
match input {
GOD => {} //~ HELP you might have meant to pattern match against the value of similarly named constant `god`
//~^ NOTE matches any value
_ => {} //~ ERROR unreachable pattern
//~^ NOTE no value can reach this
}
match input {
GOOOD => {} //~ HELP you might have meant to pattern match against the value of similarly named constant `GOOD`
//~^ NOTE matches any value
_ => {} //~ ERROR unreachable pattern
//~^ NOTE no value can reach this
}
match input {
name => {}
//~^ NOTE matches any value
_ => {} //~ ERROR unreachable pattern
//~^ NOTE no value can reach this
}
match "" {
ARCH => {} //~ HELP you might have meant to pattern match against the value of constant `ARCH`
//~^ NOTE matches any value
_ => {} //~ ERROR unreachable pattern
//~^ NOTE no value can reach this
}
}

View File

@ -0,0 +1,78 @@
error: unreachable pattern
--> $DIR/const-with-typo-in-pattern-binding.rs:18:9
|
LL | X => {}
| - matches any value
LL | _ => {}
| ^ no value can reach this
|
note: there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope
--> $DIR/const-with-typo-in-pattern-binding.rs:5:5
|
LL | const X: i32 = 0;
| ^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/const-with-typo-in-pattern-binding.rs:1:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/const-with-typo-in-pattern-binding.rs:24:9
|
LL | GOD => {}
| --- matches any value
LL |
LL | _ => {}
| ^ no value can reach this
|
help: you might have meant to pattern match against the value of similarly named constant `god` instead of introducing a new catch-all binding
|
LL | god => {}
| ~~~
error: unreachable pattern
--> $DIR/const-with-typo-in-pattern-binding.rs:30:9
|
LL | GOOOD => {}
| ----- matches any value
LL |
LL | _ => {}
| ^ no value can reach this
|
help: you might have meant to pattern match against the value of similarly named constant `GOOD` instead of introducing a new catch-all binding
|
LL | GOOD => {}
| ~~~~
error: unreachable pattern
--> $DIR/const-with-typo-in-pattern-binding.rs:36:9
|
LL | name => {}
| ---- matches any value
LL |
LL | _ => {}
| ^ no value can reach this
|
note: there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings
--> $DIR/const-with-typo-in-pattern-binding.rs:14:9
|
LL | let name: i32 = 42;
| ^^^^
error: unreachable pattern
--> $DIR/const-with-typo-in-pattern-binding.rs:42:9
|
LL | ARCH => {}
| ---- matches any value
LL |
LL | _ => {}
| ^ no value can reach this
|
help: you might have meant to pattern match against the value of constant `ARCH` instead of introducing a new catch-all binding
|
LL | std::env::consts::ARCH => {}
| ~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors

View File

@ -17,7 +17,6 @@ impl<T, D> MyTrait<T> for D {
}
impl<T> MyTrait<T> for BadStruct {
//~^ ERROR: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
fn foo() {}
}

View File

@ -4,16 +4,6 @@ error[E0412]: cannot find type `MissingType` in this scope
LL | err: MissingType
| ^^^^^^^^^^^ not found in this scope
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
--> $DIR/issue-68830-spurious-diagnostics.rs:19:1
|
LL | impl<T, D> MyTrait<T> for D {
| --------------------------- first implementation here
...
LL | impl<T> MyTrait<T> for BadStruct {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `BadStruct`
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0119, E0412.
For more information about an error, try `rustc --explain E0119`.
For more information about this error, try `rustc --explain E0412`.

View File

@ -1,5 +1,6 @@
fn function<T: PartialEq>() {
foo == 2; //~ ERROR cannot find value `foo` in this scope [E0425]
//~^ ERROR mismatched types
}
fn main() {}

View File

@ -4,6 +4,18 @@ error[E0425]: cannot find value `foo` in this scope
LL | foo == 2;
| ^^^ not found in this scope
error: aborting due to 1 previous error
error[E0308]: mismatched types
--> $DIR/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs:2:12
|
LL | fn function<T: PartialEq>() {
| - expected this type parameter
LL | foo == 2;
| ^ expected type parameter `T`, found integer
|
= note: expected type parameter `T`
found type `{integer}`
For more information about this error, try `rustc --explain E0425`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`.

View File

@ -10,5 +10,4 @@ trait X<T> {
}
trait Marker {}
impl Marker for dyn Foo {}
//~^ ERROR cannot be made into an object
fn main() {}

View File

@ -55,24 +55,6 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
= help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/issue-78372.rs:12:17
|
LL | fn foo(self: Smaht<Self, T>);
| -------------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
...
LL | impl Marker for dyn Foo {}
| ^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-78372.rs:9:18
|
LL | trait Foo: X<u32> {}
| --- this trait cannot be made into an object...
LL | trait X<T> {
LL | fn foo(self: Smaht<Self, T>);
| ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
error[E0307]: invalid `self` parameter type: `Smaht<Self, T>`
--> $DIR/issue-78372.rs:9:18
|
@ -88,7 +70,7 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion
LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658.
For more information about an error, try `rustc --explain E0038`.
Some errors have detailed explanations: E0307, E0378, E0412, E0658.
For more information about an error, try `rustc --explain E0307`.

View File

@ -10,6 +10,7 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() {
let b: &dyn FromResidual = &();
//~^ ERROR: the trait `FromResidual` cannot be made into an object
//~| ERROR: the trait `FromResidual` cannot be made into an object
//~| ERROR: the trait `FromResidual` cannot be made into an object
}
fn main() {}

View File

@ -6,6 +6,29 @@ LL | let b: &dyn FromResidual = &();
|
= note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
error[E0038]: the trait `FromResidual` cannot be made into an object
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32
|
LL | let b: &dyn FromResidual = &();
| ^^^ `FromResidual` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
|
LL | trait FromResidual<R = <Self as Try>::Residual> {
| ------------ this trait cannot be made into an object...
LL | fn from_residual(residual: R) -> Self;
| ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter
= note: required for the cast from `&()` to `&dyn FromResidual<{type error}>`
help: consider turning `from_residual` into a method by giving it a `&self` argument
|
LL | fn from_residual(&self, residual: R) -> Self;
| ++++++
help: alternatively, consider constraining `from_residual` so it does not apply to trait objects
|
LL | fn from_residual(residual: R) -> Self where Self: Sized;
| +++++++++++++++++
error[E0038]: the trait `FromResidual` cannot be made into an object
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12
|
@ -28,6 +51,6 @@ help: alternatively, consider constraining `from_residual` so it does not apply
LL | fn from_residual(residual: R) -> Self where Self: Sized;
| +++++++++++++++++
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.

View File

@ -6,8 +6,7 @@ impl<'a> Bar for Foo<'f> { //~ ERROR undeclared lifetime
type Type = u32;
}
fn test() //~ ERROR the trait bound `for<'a> Foo<'a>: Bar` is not satisfied
//~| ERROR the trait bound `for<'a> Foo<'a>: Bar` is not satisfied
fn test()
where
for<'a> <Foo<'a> as Bar>::Type: Sized,
{

View File

@ -6,22 +6,6 @@ LL | impl<'a> Bar for Foo<'f> {
| |
| help: consider introducing lifetime `'f` here: `'f,`
error[E0277]: the trait bound `for<'a> Foo<'a>: Bar` is not satisfied
--> $DIR/span-bug-issue-121414.rs:9:1
|
LL | / fn test()
LL | |
LL | | where
LL | | for<'a> <Foo<'a> as Bar>::Type: Sized,
| |__________________________________________^ the trait `for<'a> Bar` is not implemented for `Foo<'a>`
error: aborting due to 1 previous error
error[E0277]: the trait bound `for<'a> Foo<'a>: Bar` is not satisfied
--> $DIR/span-bug-issue-121414.rs:9:4
|
LL | fn test()
| ^^^^ the trait `for<'a> Bar` is not implemented for `Foo<'a>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0261, E0277.
For more information about an error, try `rustc --explain E0261`.
For more information about this error, try `rustc --explain E0261`.

View File

@ -0,0 +1,21 @@
// regression test for #127353
#![feature(type_alias_impl_trait)]
trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>;
//~^ ERROR unconstrained opaque type
pub enum UninhabitedVariants {
Tuple(Alias),
//~^ ERROR missing lifetime specifier
//~| ERROR missing generics
//~| ERROR non-defining opaque type use in defining scope
}
fn uwu(x: UninhabitedVariants) {
//~^ ERROR item does not constrain
match x {}
//~^ ERROR non-exhaustive patterns
}
fn main() {}

View File

@ -0,0 +1,86 @@
error[E0106]: missing lifetime specifier
--> $DIR/bad-tait-no-substs.rs:9:11
|
LL | Tuple(Alias),
| ^^^^^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL ~ pub enum UninhabitedVariants<'a> {
LL ~ Tuple(Alias<'a>),
|
error[E0107]: missing generics for type alias `Alias`
--> $DIR/bad-tait-no-substs.rs:9:11
|
LL | Tuple(Alias),
| ^^^^^ expected 1 generic argument
|
note: type alias defined here, with 1 generic parameter: `U`
--> $DIR/bad-tait-no-substs.rs:5:6
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^ -
help: add missing generic argument
|
LL | Tuple(Alias<U>),
| +++
error[E0792]: non-defining opaque type use in defining scope
--> $DIR/bad-tait-no-substs.rs:9:11
|
LL | Tuple(Alias),
| ^^^^^ argument `'_` is not a generic parameter
|
note: for this opaque type
--> $DIR/bad-tait-no-substs.rs:5:21
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^^^^^^^^^
error: item does not constrain `Alias::{opaque#0}`, but has it in its signature
--> $DIR/bad-tait-no-substs.rs:15:4
|
LL | fn uwu(x: UninhabitedVariants) {
| ^^^
|
= note: consider moving the opaque type's declaration and defining uses into a separate module
note: this opaque type is in the signature
--> $DIR/bad-tait-no-substs.rs:5:21
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^^^^^^^^^
error: unconstrained opaque type
--> $DIR/bad-tait-no-substs.rs:5:21
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^^^^^^^^^
|
= note: `Alias` must be used in combination with a concrete type within the same module
error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered
--> $DIR/bad-tait-no-substs.rs:17:11
|
LL | match x {}
| ^ pattern `UninhabitedVariants::Tuple(_)` not covered
|
note: `UninhabitedVariants` defined here
--> $DIR/bad-tait-no-substs.rs:8:10
|
LL | pub enum UninhabitedVariants {
| ^^^^^^^^^^^^^^^^^^^
LL | Tuple(Alias),
| ----- not covered
= note: the matched value is of type `UninhabitedVariants`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ match x {
LL + UninhabitedVariants::Tuple(_) => todo!(),
LL + }
|
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0004, E0106, E0107, E0792.
For more information about an error, try `rustc --explain E0004`.

View File

@ -0,0 +1,22 @@
// regression test for rust-lang/rust#125758
#![feature(impl_trait_in_assoc_type)]
trait Trait {
type Assoc2;
}
struct Bar;
impl Trait for Bar {
type Assoc2 = impl std::fmt::Debug;
//~^ ERROR unconstrained opaque type
}
struct Foo {
field: <Bar as Trait>::Assoc2,
}
static BAR: u8 = 42;
static FOO2: &Foo = unsafe { std::mem::transmute(&BAR) };
fn main() {}

View File

@ -0,0 +1,10 @@
error: unconstrained opaque type
--> $DIR/bad-transmute-itiat.rs:11:19
|
LL | type Assoc2 = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: `Assoc2` must be used in combination with a concrete type within the same impl
error: aborting due to 1 previous error

View File

@ -1,8 +1,11 @@
//@ known-bug: #130956
// Regression test for #130956
#![feature(type_alias_impl_trait)]
mod impl_trait_mod {
use super::*;
pub type OpaqueBlock = impl Trait;
//~^ ERROR unconstrained opaque type
pub type OpaqueIf = impl Trait;
pub struct BlockWrapper(OpaqueBlock);

View File

@ -0,0 +1,10 @@
error: unconstrained opaque type
--> $DIR/drop-analysis-on-unconstrained-tait.rs:7:28
|
LL | pub type OpaqueBlock = impl Trait;
| ^^^^^^^^^^
|
= note: `OpaqueBlock` must be used in combination with a concrete type within the same module
error: aborting due to 1 previous error

View File

@ -14,5 +14,4 @@ impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here
extern "C" {
pub fn repro(_: Wrapper<Ref>);
//~^ ERROR the trait bound `Ref<'_>: Trait` is not satisfied
}

View File

@ -9,19 +9,6 @@ help: indicate the anonymous lifetime
LL | impl Trait for Ref<'_> {}
| ++++
error[E0277]: the trait bound `Ref<'_>: Trait` is not satisfied
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
|
LL | pub fn repro(_: Wrapper<Ref>);
| ^^^^^^^^^^^^ the trait `Trait` is not implemented for `Ref<'_>`
|
note: required by a bound in `Wrapper`
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23
|
LL | pub struct Wrapper<T: Trait>(T);
| ^^^^^ required by this bound in `Wrapper`
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0726.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0726`.