mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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:
commit
c49a687d63
@ -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()
|
||||
|
@ -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>>>,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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>,
|
||||
|
@ -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"),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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 } =
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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>,
|
||||
|
@ -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>
|
48
tests/codegen/aarch64-softfloat.rs
Normal file
48
tests/codegen/aarch64-softfloat.rs
Normal 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
|
||||
}
|
@ -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> {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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 };
|
@ -6,7 +6,7 @@ struct Vtable(dyn Cap);
|
||||
trait Cap<'a> {}
|
||||
|
||||
union Transmute {
|
||||
t: u64,
|
||||
t: u128,
|
||||
u: &'static Vtable,
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
}
|
@ -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`.
|
@ -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 {
|
||||
|
18
tests/ui/const-generics/generic_const_exprs/bad-multiply.rs
Normal file
18
tests/ui/const-generics/generic_const_exprs/bad-multiply.rs
Normal 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() {}
|
@ -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`.
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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`.
|
||||
|
18
tests/ui/lazy-type-alias/bad-lazy-type-alias.rs
Normal file
18
tests/ui/lazy-type-alias/bad-lazy-type-alias.rs
Normal 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() {}
|
28
tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr
Normal file
28
tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr
Normal 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`.
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
45
tests/ui/resolve/const-with-typo-in-pattern-binding.rs
Normal file
45
tests/ui/resolve/const-with-typo-in-pattern-binding.rs
Normal 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
|
||||
}
|
||||
}
|
78
tests/ui/resolve/const-with-typo-in-pattern-binding.stderr
Normal file
78
tests/ui/resolve/const-with-typo-in-pattern-binding.stderr
Normal 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
|
||||
|
@ -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() {}
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -1,5 +1,6 @@
|
||||
fn function<T: PartialEq>() {
|
||||
foo == 2; //~ ERROR cannot find value `foo` in this scope [E0425]
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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`.
|
||||
|
@ -10,5 +10,4 @@ trait X<T> {
|
||||
}
|
||||
trait Marker {}
|
||||
impl Marker for dyn Foo {}
|
||||
//~^ ERROR cannot be made into an object
|
||||
fn main() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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`.
|
||||
|
21
tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
Normal file
21
tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
Normal 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() {}
|
86
tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
Normal file
86
tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
Normal 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`.
|
22
tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs
Normal file
22
tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs
Normal 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() {}
|
10
tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr
Normal file
10
tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr
Normal 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
|
||||
|
@ -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);
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user