Auto merge of #128222 - tgross35:rollup-fk7qdo3, r=tgross35
Rollup of 7 pull requests Successful merges: - #126575 (Make it crystal clear what lint `type_alias_bounds` actually signifies) - #127017 (Extend rules of dead code analysis for impls for adts to impls for types refer to adts) - #127523 (Migrate `dump-ice-to-disk` and `panic-abort-eh_frame` `run-make` tests to rmake) - #127557 (Add a label to point to the lacking macro name definition) - #127989 (Migrate `interdependent-c-libraries`, `compiler-rt-works-on-mingw` and `incr-foreign-head-span` `run-make` tests to rmake) - #128099 (migrate tests/run-make/extern-flag-disambiguates to rmake) - #128170 (Make Clone::clone a lang item) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
83d67685ac
@ -162,6 +162,7 @@ language_item_table! {
|
||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
||||
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
||||
CloneFn, sym::clone_fn, clone_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
||||
/// The associated item of the `DiscriminantKind` trait.
|
||||
|
@ -1,4 +1,4 @@
|
||||
hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$ty_param_name}`
|
||||
hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$qself}`
|
||||
.label = ambiguous associated {$assoc_kind} `{$assoc_name}`
|
||||
|
||||
hir_analysis_ambiguous_lifetime_bound =
|
||||
@ -12,16 +12,21 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private
|
||||
.label = private {$kind}
|
||||
.defined_here_label = the {$kind} is defined here
|
||||
|
||||
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
|
||||
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$qself}`
|
||||
|
||||
hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
|
||||
[true] an
|
||||
*[false] a similarly named
|
||||
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
|
||||
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
|
||||
hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind}
|
||||
hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind}
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg =
|
||||
consider fully qualifying{$identically_named ->
|
||||
[true] {""}
|
||||
*[false] {" "}and renaming
|
||||
} the associated {$assoc_kind}
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name
|
||||
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
|
||||
|
||||
hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
|
||||
|
@ -22,7 +22,7 @@ pub struct AmbiguousAssocItem<'a> {
|
||||
pub span: Span,
|
||||
pub assoc_kind: &'static str,
|
||||
pub assoc_name: Ident,
|
||||
pub ty_param_name: &'a str,
|
||||
pub qself: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -75,7 +75,7 @@ pub struct AssocItemNotFound<'a> {
|
||||
pub span: Span,
|
||||
pub assoc_name: Ident,
|
||||
pub assoc_kind: &'static str,
|
||||
pub ty_param_name: &'a str,
|
||||
pub qself: &'a str,
|
||||
#[subdiagnostic]
|
||||
pub label: Option<AssocItemNotFoundLabel<'a>>,
|
||||
#[subdiagnostic]
|
||||
@ -126,13 +126,32 @@ pub enum AssocItemNotFoundSugg<'a> {
|
||||
assoc_kind: &'static str,
|
||||
suggested_name: Symbol,
|
||||
},
|
||||
#[suggestion(hir_analysis_assoc_item_not_found_other_sugg, code = "{suggested_name}")]
|
||||
#[multipart_suggestion(
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg,
|
||||
style = "verbose"
|
||||
)]
|
||||
SimilarInOtherTraitQPath {
|
||||
#[suggestion_part(code = "<")]
|
||||
lo: Span,
|
||||
#[suggestion_part(code = " as {trait_ref}>")]
|
||||
mi: Span,
|
||||
#[suggestion_part(code = "{suggested_name}")]
|
||||
hi: Option<Span>,
|
||||
trait_ref: String,
|
||||
suggested_name: Symbol,
|
||||
identically_named: bool,
|
||||
#[applicability]
|
||||
applicability: Applicability,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_analysis_assoc_item_not_found_other_sugg,
|
||||
code = "{suggested_name}",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
Other {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
#[applicability]
|
||||
applicability: Applicability,
|
||||
ty_param_name: &'a str,
|
||||
qself: &'a str,
|
||||
assoc_kind: &'static str,
|
||||
suggested_name: Symbol,
|
||||
},
|
||||
|
@ -6,7 +6,6 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
@ -16,9 +15,8 @@ use smallvec::SmallVec;
|
||||
|
||||
use crate::bounds::Bounds;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
|
||||
|
||||
use super::RegionInferReason;
|
||||
use crate::hir_ty_lowering::HirTyLowerer;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, OnlySelfBounds, PredicateFilter, RegionInferReason};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Add a `Sized` bound to the `bounds` if appropriate.
|
||||
@ -288,8 +286,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
// one that does define it.
|
||||
self.probe_single_bound_for_assoc_item(
|
||||
|| traits::supertraits(tcx, trait_ref),
|
||||
trait_ref.skip_binder().print_only_trait_name(),
|
||||
None,
|
||||
AssocItemQSelf::Trait(trait_ref.def_id()),
|
||||
assoc_kind,
|
||||
constraint.ident,
|
||||
path_span,
|
||||
|
@ -3,7 +3,7 @@ use crate::errors::{
|
||||
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::hir_ty_lowering::HirTyLowerer;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
@ -11,9 +11,9 @@ use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{
|
||||
codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, Node};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Key;
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
@ -116,8 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
pub(super) fn complain_about_assoc_item_not_found<I>(
|
||||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
ty_param_name: &str,
|
||||
ty_param_def_id: Option<LocalDefId>,
|
||||
qself: AssocItemQSelf,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
@ -139,7 +138,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
);
|
||||
}
|
||||
|
||||
let assoc_kind_str = super::assoc_kind_str(assoc_kind);
|
||||
let assoc_kind_str = assoc_kind_str(assoc_kind);
|
||||
let qself_str = qself.to_string(tcx);
|
||||
|
||||
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
|
||||
// valid span, so we point at the whole path segment instead.
|
||||
@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
span: if is_dummy { span } else { assoc_name.span },
|
||||
assoc_name,
|
||||
assoc_kind: assoc_kind_str,
|
||||
ty_param_name,
|
||||
qself: &qself_str,
|
||||
label: None,
|
||||
sugg: None,
|
||||
};
|
||||
@ -219,19 +219,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
suggested_name,
|
||||
identically_named: suggested_name == assoc_name.name,
|
||||
});
|
||||
let hir = tcx.hir();
|
||||
if let Some(def_id) = ty_param_def_id
|
||||
&& let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id))
|
||||
&& let Some(generics) = hir.get_generics(parent.def_id)
|
||||
if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
|
||||
// Not using `self.item_def_id()` here as that would yield the opaque type itself if we're
|
||||
// inside an opaque type while we're interested in the overarching type alias (TAIT).
|
||||
// FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
|
||||
&& let item_def_id =
|
||||
tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
|
||||
// FIXME: ...which obviously won't have any generics.
|
||||
&& let Some(generics) = tcx.hir().get_generics(item_def_id.def_id)
|
||||
{
|
||||
if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any(
|
||||
|b| match b {
|
||||
// FIXME: Suggest adding supertrait bounds if we have a `Self` type param.
|
||||
// FIXME(trait_alias): Suggest adding `Self: Trait` to
|
||||
// `trait Alias = where Self::Proj:;` with `trait Trait { type Proj; }`.
|
||||
if generics
|
||||
.bounds_for_param(ty_param_def_id)
|
||||
.flat_map(|pred| pred.bounds.iter())
|
||||
.any(|b| match b {
|
||||
hir::GenericBound::Trait(t, ..) => {
|
||||
t.trait_ref.trait_def_id() == Some(best_trait)
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
) {
|
||||
})
|
||||
{
|
||||
// The type param already has a bound for `trait_name`, we just need to
|
||||
// change the associated item.
|
||||
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
|
||||
@ -242,48 +251,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
return self.dcx().emit_err(err);
|
||||
}
|
||||
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if suggest_constraining_type_param(
|
||||
tcx,
|
||||
generics,
|
||||
&mut err,
|
||||
&ty_param_name,
|
||||
&trait_name,
|
||||
None,
|
||||
None,
|
||||
) && suggested_name != assoc_name.name
|
||||
let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
|
||||
let mut trait_ref = trait_name.clone();
|
||||
let applicability = if let [arg, args @ ..] = trait_args {
|
||||
use std::fmt::Write;
|
||||
write!(trait_ref, "</* {arg}").unwrap();
|
||||
args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap();
|
||||
trait_ref += " */>";
|
||||
Applicability::HasPlaceholders
|
||||
} else {
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
|
||||
let identically_named = suggested_name == assoc_name.name;
|
||||
|
||||
if let DefKind::TyAlias = tcx.def_kind(item_def_id)
|
||||
&& !tcx.type_alias_is_lazy(item_def_id)
|
||||
{
|
||||
// We suggested constraining a type parameter, but the associated item on it
|
||||
// was also not an exact match, so we also suggest changing it.
|
||||
err.span_suggestion_verbose(
|
||||
assoc_name.span,
|
||||
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
|
||||
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
|
||||
lo: ty_param_span.shrink_to_lo(),
|
||||
mi: ty_param_span.shrink_to_hi(),
|
||||
hi: (!identically_named).then_some(assoc_name.span),
|
||||
trait_ref,
|
||||
identically_named,
|
||||
suggested_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
applicability,
|
||||
});
|
||||
} else {
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if suggest_constraining_type_param(
|
||||
tcx, generics, &mut err, &qself_str, &trait_ref, None, None,
|
||||
) && !identically_named
|
||||
{
|
||||
// We suggested constraining a type parameter, but the associated item on it
|
||||
// was also not an exact match, so we also suggest changing it.
|
||||
err.span_suggestion_verbose(
|
||||
assoc_name.span,
|
||||
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
|
||||
suggested_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
return err.emit();
|
||||
}
|
||||
return err.emit();
|
||||
}
|
||||
return self.dcx().emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
// If we still couldn't find any associated item, and only one associated item exists,
|
||||
// suggests using it.
|
||||
// suggest using it.
|
||||
if let [candidate_name] = all_candidate_names.as_slice() {
|
||||
// This should still compile, except on `#![feature(associated_type_defaults)]`
|
||||
// where it could suggests `type A = Self::A`, thus recursing infinitely.
|
||||
let applicability =
|
||||
if assoc_kind == ty::AssocKind::Type && tcx.features().associated_type_defaults {
|
||||
Applicability::Unspecified
|
||||
} else {
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
|
||||
err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
|
||||
span: assoc_name.span,
|
||||
applicability,
|
||||
ty_param_name,
|
||||
qself: &qself_str,
|
||||
assoc_kind: assoc_kind_str,
|
||||
suggested_name: *candidate_name,
|
||||
});
|
||||
@ -349,10 +370,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
self.dcx().emit_err(errors::AssocKindMismatch {
|
||||
span,
|
||||
expected: super::assoc_kind_str(expected),
|
||||
got: super::assoc_kind_str(got),
|
||||
expected: assoc_kind_str(expected),
|
||||
got: assoc_kind_str(got),
|
||||
expected_because_label,
|
||||
assoc_kind: super::assoc_kind_str(assoc_item.kind),
|
||||
assoc_kind: assoc_kind_str(assoc_item.kind),
|
||||
def_span: tcx.def_span(assoc_item.def_id),
|
||||
bound_on_assoc_const_label,
|
||||
wrap_in_braces_sugg,
|
||||
@ -746,7 +767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
|
||||
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
|
||||
in_expr_or_pat = match grandparent {
|
||||
Node::Expr(_) | Node::Pat(_) => true,
|
||||
hir::Node::Expr(_) | hir::Node::Pat(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
match bound.trait_ref.path.segments {
|
||||
@ -1612,3 +1633,11 @@ fn generics_args_err_extend<'a>(
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
|
||||
match kind {
|
||||
ty::AssocKind::Fn => "function",
|
||||
ty::AssocKind::Const => "constant",
|
||||
ty::AssocKind::Type => "type",
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::wf::object_region_bounds;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::slice;
|
||||
|
||||
/// A path segment that is semantically allowed to have generic arguments.
|
||||
@ -193,6 +192,25 @@ pub trait HirTyLowerer<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The "qualified self" of an associated item path.
|
||||
///
|
||||
/// For diagnostic purposes only.
|
||||
enum AssocItemQSelf {
|
||||
Trait(DefId),
|
||||
TyParam(LocalDefId, Span),
|
||||
SelfTyAlias,
|
||||
}
|
||||
|
||||
impl AssocItemQSelf {
|
||||
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
|
||||
match *self {
|
||||
Self::Trait(def_id) => tcx.def_path_str(def_id),
|
||||
Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(),
|
||||
Self::SelfTyAlias => kw::SelfUpper.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
||||
/// are present in a set of generic arguments.
|
||||
///
|
||||
@ -802,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
fn probe_single_ty_param_bound_for_assoc_ty(
|
||||
&self,
|
||||
ty_param_def_id: LocalDefId,
|
||||
ty_param_span: Span,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
||||
@ -811,19 +830,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name).predicates;
|
||||
debug!("predicates={:#?}", predicates);
|
||||
|
||||
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
|
||||
self.probe_single_bound_for_assoc_item(
|
||||
|| {
|
||||
traits::transitive_bounds_that_define_assoc_item(
|
||||
tcx,
|
||||
predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))),
|
||||
assoc_name,
|
||||
)
|
||||
let trait_refs = predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
|
||||
traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
|
||||
},
|
||||
param_name,
|
||||
Some(ty_param_def_id),
|
||||
AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
|
||||
ty::AssocKind::Type,
|
||||
assoc_name,
|
||||
span,
|
||||
@ -835,12 +849,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
///
|
||||
/// This fails if there is no such bound in the list of candidates or if there are multiple
|
||||
/// candidates in which case it reports ambiguity.
|
||||
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)]
|
||||
#[instrument(level = "debug", skip(self, all_candidates, qself, constraint), ret)]
|
||||
fn probe_single_bound_for_assoc_item<I>(
|
||||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
ty_param_name: impl Display,
|
||||
ty_param_def_id: Option<LocalDefId>,
|
||||
qself: AssocItemQSelf,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
@ -858,8 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let Some(bound) = matching_candidates.next() else {
|
||||
let reported = self.complain_about_assoc_item_not_found(
|
||||
all_candidates,
|
||||
&ty_param_name.to_string(),
|
||||
ty_param_def_id,
|
||||
qself,
|
||||
assoc_kind,
|
||||
assoc_name,
|
||||
span,
|
||||
@ -872,13 +884,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
if let Some(bound2) = matching_candidates.next() {
|
||||
debug!(?bound2);
|
||||
|
||||
let assoc_kind_str = assoc_kind_str(assoc_kind);
|
||||
let ty_param_name = &ty_param_name.to_string();
|
||||
let assoc_kind_str = errors::assoc_kind_str(assoc_kind);
|
||||
let qself_str = qself.to_string(tcx);
|
||||
let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
|
||||
span,
|
||||
assoc_kind: assoc_kind_str,
|
||||
assoc_name,
|
||||
ty_param_name,
|
||||
qself: &qself_str,
|
||||
});
|
||||
// Provide a more specific error code index entry for equality bindings.
|
||||
err.code(
|
||||
@ -929,7 +941,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(assoc_name.span.lo()),
|
||||
"use fully-qualified syntax to disambiguate",
|
||||
format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()),
|
||||
format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -943,7 +955,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
if !where_bounds.is_empty() {
|
||||
err.help(format!(
|
||||
"consider introducing a new type parameter `T` and adding `where` constraints:\
|
||||
\n where\n T: {ty_param_name},\n{}",
|
||||
\n where\n T: {qself_str},\n{}",
|
||||
where_bounds.join(",\n"),
|
||||
));
|
||||
}
|
||||
@ -997,11 +1009,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let assoc_ident = assoc_segment.ident;
|
||||
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
|
||||
path.res
|
||||
} else {
|
||||
Res::Err
|
||||
};
|
||||
|
||||
// Check if we have an enum variant or an inherent associated type.
|
||||
let mut variant_resolution = None;
|
||||
@ -1038,6 +1045,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
}
|
||||
}
|
||||
|
||||
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
|
||||
path.res
|
||||
} else {
|
||||
Res::Err
|
||||
};
|
||||
|
||||
// Find the type of the associated item, and the trait where the associated
|
||||
// item is declared.
|
||||
let bound = match (&qself_ty.kind(), qself_res) {
|
||||
@ -1056,8 +1069,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
ty::Binder::dummy(trait_ref.instantiate_identity()),
|
||||
)
|
||||
},
|
||||
kw::SelfUpper,
|
||||
None,
|
||||
AssocItemQSelf::SelfTyAlias,
|
||||
ty::AssocKind::Type,
|
||||
assoc_ident,
|
||||
span,
|
||||
@ -1069,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
|
||||
) => self.probe_single_ty_param_bound_for_assoc_ty(
|
||||
param_did.expect_local(),
|
||||
qself.span,
|
||||
assoc_ident,
|
||||
span,
|
||||
)?,
|
||||
@ -2522,11 +2535,3 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Some(r)
|
||||
}
|
||||
}
|
||||
|
||||
fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
|
||||
match kind {
|
||||
ty::AssocKind::Fn => "function",
|
||||
ty::AssocKind::Const => "constant",
|
||||
ty::AssocKind::Type => "type",
|
||||
}
|
||||
}
|
||||
|
@ -144,13 +144,18 @@ lint_builtin_special_module_name_used_main = found module declaration for main.r
|
||||
|
||||
lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
|
||||
|
||||
lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
|
||||
|
||||
lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
|
||||
.suggestion = the bound will not be checked when the type alias is used, and should be removed
|
||||
|
||||
lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
|
||||
.suggestion = the clause will not be checked when the type alias is used, and should be removed
|
||||
lint_builtin_type_alias_bounds_enable_feat_help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
lint_builtin_type_alias_bounds_label = will not be checked at usage sites of the type alias
|
||||
lint_builtin_type_alias_bounds_limitation_note = this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
lint_builtin_type_alias_bounds_param_bounds = bounds on generic parameters in type aliases are not enforced
|
||||
.suggestion = remove {$count ->
|
||||
[one] this bound
|
||||
*[other] these bounds
|
||||
}
|
||||
lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg = fully qualify this associated type
|
||||
lint_builtin_type_alias_bounds_where_clause = where clauses on type aliases are not enforced
|
||||
.suggestion = remove this where clause
|
||||
|
||||
lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
|
||||
lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
||||
|
@ -31,12 +31,11 @@ use crate::{
|
||||
BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
|
||||
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
|
||||
BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
|
||||
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds,
|
||||
BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause,
|
||||
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
|
||||
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
|
||||
BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe,
|
||||
BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
|
||||
BuiltinWhileTrue, InvalidAsmLabel, SuggestChangingAssocTypes,
|
||||
BuiltinWhileTrue, InvalidAsmLabel,
|
||||
},
|
||||
EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
|
||||
};
|
||||
@ -1391,64 +1390,80 @@ declare_lint! {
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The trait bounds in a type alias are currently ignored, and should not
|
||||
/// be included to avoid confusion. This was previously allowed
|
||||
/// unintentionally; this may become a hard error in the future.
|
||||
/// Trait and lifetime bounds on generic parameters and in where clauses of
|
||||
/// type aliases are not checked at usage sites of the type alias. Moreover,
|
||||
/// they are not thoroughly checked for correctness at their definition site
|
||||
/// either similar to the aliased type.
|
||||
///
|
||||
/// This is a known limitation of the type checker that may be lifted in a
|
||||
/// future edition. Permitting such bounds in light of this was unintentional.
|
||||
///
|
||||
/// While these bounds may have secondary effects such as enabling the use of
|
||||
/// "shorthand" associated type paths[^1] and affecting the default trait
|
||||
/// object lifetime[^2] of trait object types passed to the type alias, this
|
||||
/// should not have been allowed until the aforementioned restrictions of the
|
||||
/// type checker have been lifted.
|
||||
///
|
||||
/// Using such bounds is highly discouraged as they are actively misleading.
|
||||
///
|
||||
/// [^1]: I.e., paths of the form `T::Assoc` where `T` is a type parameter
|
||||
/// bounded by trait `Trait` which defines an associated type called `Assoc`
|
||||
/// as opposed to a fully qualified path of the form `<T as Trait>::Assoc`.
|
||||
/// [^2]: <https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes>
|
||||
TYPE_ALIAS_BOUNDS,
|
||||
Warn,
|
||||
"bounds in type aliases are not enforced"
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
/// Lint for trait and lifetime bounds in type aliases being mostly ignored.
|
||||
/// They are relevant when using associated types, but otherwise neither checked
|
||||
/// at definition site nor enforced at use site.
|
||||
TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
|
||||
);
|
||||
declare_lint_pass!(TypeAliasBounds => [TYPE_ALIAS_BOUNDS]);
|
||||
|
||||
impl TypeAliasBounds {
|
||||
pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool {
|
||||
match *qpath {
|
||||
hir::QPath::TypeRelative(ty, _) => {
|
||||
// If this is a type variable, we found a `T::Assoc`.
|
||||
match ty.kind {
|
||||
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
|
||||
matches!(path.res, Res::Def(DefKind::TyParam, _))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false,
|
||||
pub(crate) fn affects_object_lifetime_defaults(pred: &hir::WherePredicate<'_>) -> bool {
|
||||
// Bounds of the form `T: 'a` with `T` type param affect object lifetime defaults.
|
||||
if let hir::WherePredicate::BoundPredicate(pred) = pred
|
||||
&& pred.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Outlives(_)))
|
||||
&& pred.bound_generic_params.is_empty() // indeed, even if absent from the RHS
|
||||
&& pred.bounded_ty.as_generic_param().is_some()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
|
||||
let hir::ItemKind::TyAlias(hir_ty, generics) = item.kind else { return };
|
||||
|
||||
// There must not be a where clause.
|
||||
if generics.predicates.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bounds of lazy type aliases and TAITs are respected.
|
||||
if cx.tcx.type_alias_is_lazy(item.owner_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty = cx.tcx.type_of(item.owner_id).skip_binder();
|
||||
if ty.has_inherent_projections() {
|
||||
// Bounds of type aliases that contain opaque types or inherent projections are
|
||||
// respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X =
|
||||
// Type::Inherent;`.
|
||||
// FIXME(generic_const_exprs): Revisit this before stabilization.
|
||||
// See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`.
|
||||
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||
if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)
|
||||
&& cx.tcx.features().generic_const_exprs
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// There must not be a where clause
|
||||
if type_alias_generics.predicates.is_empty() {
|
||||
return;
|
||||
}
|
||||
// NOTE(inherent_associated_types): While we currently do take some bounds in type
|
||||
// aliases into consideration during IAT *selection*, we don't perform full use+def
|
||||
// site wfchecking for such type aliases. Therefore TAB should still trigger.
|
||||
// See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`.
|
||||
|
||||
let mut where_spans = Vec::new();
|
||||
let mut inline_spans = Vec::new();
|
||||
let mut inline_sugg = Vec::new();
|
||||
for p in type_alias_generics.predicates {
|
||||
|
||||
for p in generics.predicates {
|
||||
let span = p.span();
|
||||
if p.in_where_clause() {
|
||||
where_spans.push(span);
|
||||
@ -1460,37 +1475,57 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||
}
|
||||
}
|
||||
|
||||
let mut suggested_changing_assoc_types = false;
|
||||
if !where_spans.is_empty() {
|
||||
let sub = (!suggested_changing_assoc_types).then(|| {
|
||||
suggested_changing_assoc_types = true;
|
||||
SuggestChangingAssocTypes { ty: hir_ty }
|
||||
});
|
||||
let mut ty = Some(hir_ty);
|
||||
let enable_feat_help = cx.tcx.sess.is_nightly_build();
|
||||
|
||||
if let [.., label_sp] = *where_spans {
|
||||
cx.emit_span_lint(
|
||||
TYPE_ALIAS_BOUNDS,
|
||||
where_spans,
|
||||
BuiltinTypeAliasWhereClause {
|
||||
suggestion: type_alias_generics.where_clause_span,
|
||||
sub,
|
||||
BuiltinTypeAliasBounds {
|
||||
in_where_clause: true,
|
||||
label: label_sp,
|
||||
enable_feat_help,
|
||||
suggestions: vec![(generics.where_clause_span, String::new())],
|
||||
preds: generics.predicates,
|
||||
ty: ty.take(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if !inline_spans.is_empty() {
|
||||
let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg };
|
||||
let sub = (!suggested_changing_assoc_types).then(|| {
|
||||
suggested_changing_assoc_types = true;
|
||||
SuggestChangingAssocTypes { ty: hir_ty }
|
||||
});
|
||||
if let [.., label_sp] = *inline_spans {
|
||||
cx.emit_span_lint(
|
||||
TYPE_ALIAS_BOUNDS,
|
||||
inline_spans,
|
||||
BuiltinTypeAliasGenericBounds { suggestion, sub },
|
||||
BuiltinTypeAliasBounds {
|
||||
in_where_clause: false,
|
||||
label: label_sp,
|
||||
enable_feat_help,
|
||||
suggestions: inline_sugg,
|
||||
preds: generics.predicates,
|
||||
ty,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ShorthandAssocTyCollector {
|
||||
pub(crate) qselves: Vec<Span>,
|
||||
}
|
||||
|
||||
impl hir::intravisit::Visitor<'_> for ShorthandAssocTyCollector {
|
||||
fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, _: Span) {
|
||||
// Look for "type-parameter shorthand-associated-types". I.e., paths of the
|
||||
// form `T::Assoc` with `T` type param. These are reliant on trait bounds.
|
||||
if let hir::QPath::TypeRelative(qself, _) = qpath
|
||||
&& qself.as_generic_param().is_some()
|
||||
{
|
||||
self.qselves.push(qself.span);
|
||||
}
|
||||
hir::intravisit::walk_qpath(self, qpath, id)
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `trivial_bounds` lint detects trait bounds that don't depend on
|
||||
/// any type parameters.
|
||||
|
@ -2,14 +2,16 @@
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
use std::num::NonZero;
|
||||
|
||||
use crate::errors::RequestedLevel;
|
||||
use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
|
||||
use crate::errors::{OverruledAttributeSub, RequestedLevel};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::LateContext;
|
||||
use rustc_errors::{
|
||||
codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString,
|
||||
ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp,
|
||||
Subdiagnostic, SuggestionStyle,
|
||||
};
|
||||
use rustc_hir::{def::Namespace, def_id::DefId};
|
||||
use rustc_hir::{self as hir, def::Namespace, def_id::DefId};
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{
|
||||
inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
|
||||
@ -22,10 +24,6 @@ use rustc_span::{
|
||||
Span, Symbol,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext,
|
||||
};
|
||||
|
||||
// array_into_iter.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_shadowed_into_iter)]
|
||||
@ -263,62 +261,6 @@ pub struct BuiltinUnreachablePub<'a> {
|
||||
pub help: Option<()>,
|
||||
}
|
||||
|
||||
pub struct SuggestChangingAssocTypes<'a, 'b> {
|
||||
pub ty: &'a rustc_hir::Ty<'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: &F,
|
||||
) {
|
||||
// Access to associates types should use `<T as Bound>::Assoc`, which does not need a
|
||||
// bound. Let's see if this type does that.
|
||||
|
||||
// We use a HIR visitor to walk the type.
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
struct WalkAssocTypes<'a, 'b, G: EmissionGuarantee> {
|
||||
err: &'a mut Diag<'b, G>,
|
||||
}
|
||||
impl<'a, 'b, G: EmissionGuarantee> Visitor<'_> for WalkAssocTypes<'a, 'b, G> {
|
||||
fn visit_qpath(
|
||||
&mut self,
|
||||
qpath: &rustc_hir::QPath<'_>,
|
||||
id: rustc_hir::HirId,
|
||||
span: Span,
|
||||
) {
|
||||
if TypeAliasBounds::is_type_variable_assoc(qpath) {
|
||||
self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help);
|
||||
}
|
||||
intravisit::walk_qpath(self, qpath, id)
|
||||
}
|
||||
}
|
||||
|
||||
// Let's go for a walk!
|
||||
let mut visitor = WalkAssocTypes { err: diag };
|
||||
visitor.visit_ty(self.ty);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_builtin_type_alias_where_clause)]
|
||||
pub struct BuiltinTypeAliasWhereClause<'a, 'b> {
|
||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||
pub suggestion: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_builtin_type_alias_generic_bounds)]
|
||||
pub struct BuiltinTypeAliasGenericBounds<'a, 'b> {
|
||||
#[subdiagnostic]
|
||||
pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion,
|
||||
#[subdiagnostic]
|
||||
pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_macro_expr_fragment_specifier_2024_migration)]
|
||||
pub struct MacroExprFragment2024 {
|
||||
@ -326,21 +268,72 @@ pub struct MacroExprFragment2024 {
|
||||
pub suggestion: Span,
|
||||
}
|
||||
|
||||
pub struct BuiltinTypeAliasGenericBoundsSuggestion {
|
||||
pub struct BuiltinTypeAliasBounds<'a, 'hir> {
|
||||
pub in_where_clause: bool,
|
||||
pub label: Span,
|
||||
pub enable_feat_help: bool,
|
||||
pub suggestions: Vec<(Span, String)>,
|
||||
pub preds: &'hir [hir::WherePredicate<'hir>],
|
||||
pub ty: Option<&'a hir::Ty<'hir>>,
|
||||
}
|
||||
|
||||
impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_suggestion,
|
||||
self.suggestions,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(if self.in_where_clause {
|
||||
fluent::lint_builtin_type_alias_bounds_where_clause
|
||||
} else {
|
||||
fluent::lint_builtin_type_alias_bounds_param_bounds
|
||||
});
|
||||
diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label);
|
||||
diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note);
|
||||
if self.enable_feat_help {
|
||||
diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help);
|
||||
}
|
||||
|
||||
// We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to
|
||||
// avoid doing throwaway work in case the lint ends up getting suppressed.
|
||||
let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() };
|
||||
if let Some(ty) = self.ty {
|
||||
hir::intravisit::Visitor::visit_ty(&mut collector, ty);
|
||||
}
|
||||
|
||||
let affect_object_lifetime_defaults = self
|
||||
.preds
|
||||
.iter()
|
||||
.filter(|pred| pred.in_where_clause() == self.in_where_clause)
|
||||
.any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred));
|
||||
|
||||
// If there are any shorthand assoc tys, then the bounds can't be removed automatically.
|
||||
// The user first needs to fully qualify the assoc tys.
|
||||
let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults {
|
||||
Applicability::MaybeIncorrect
|
||||
} else {
|
||||
Applicability::MachineApplicable
|
||||
};
|
||||
|
||||
diag.arg("count", self.suggestions.len());
|
||||
diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability);
|
||||
|
||||
// Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via
|
||||
// `<T as /* Trait */>::Assoc` to remove their reliance on any type param bounds.
|
||||
//
|
||||
// Instead of attempting to figure out the necessary trait ref, just use a
|
||||
// placeholder. Since we don't record type-dependent resolutions for non-body
|
||||
// items like type aliases, we can't simply deduce the corresp. trait from
|
||||
// the HIR path alone without rerunning parts of HIR ty lowering here
|
||||
// (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible.
|
||||
//
|
||||
// (We could employ some simple heuristics but that's likely not worth it).
|
||||
for qself in collector.qselves {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg,
|
||||
vec![
|
||||
(qself.shrink_to_lo(), "<".into()),
|
||||
(qself.shrink_to_hi(), " as /* Trait */>".into()),
|
||||
],
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
use crate::simplify::simplify_duplicate_switch_targets;
|
||||
use crate::take_array;
|
||||
use rustc_ast::attr;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::layout;
|
||||
@ -271,8 +272,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
||||
return;
|
||||
}
|
||||
|
||||
let trait_def_id = self.tcx.trait_of_item(fn_def_id);
|
||||
if trait_def_id.is_none() || trait_def_id != self.tcx.lang_items().clone_trait() {
|
||||
if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,24 @@ impl Publicness {
|
||||
}
|
||||
}
|
||||
|
||||
fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
|
||||
fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> {
|
||||
match ty.kind {
|
||||
TyKind::Path(hir::QPath::Resolved(_, path)) => {
|
||||
if let Res::Def(def_kind, def_id) = path.res
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
{
|
||||
Some((local_def_id, def_kind))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty),
|
||||
TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool {
|
||||
// treat PhantomData and positional ZST as public,
|
||||
// we don't want to lint types which only have them,
|
||||
// cause it's a common way to use such types to check things like well-formedness
|
||||
@ -79,10 +96,7 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
|
||||
/// for enum and union, just check they are public,
|
||||
/// and doesn't solve types like &T for now, just skip them
|
||||
fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness {
|
||||
if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
|
||||
&& let Res::Def(def_kind, def_id) = path.res
|
||||
&& def_id.is_local()
|
||||
{
|
||||
if let Some((def_id, def_kind)) = adt_of(ty) {
|
||||
return match def_kind {
|
||||
DefKind::Enum | DefKind::Union => {
|
||||
let ty_is_public = tcx.visibility(def_id).is_public();
|
||||
@ -565,10 +579,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
}
|
||||
|
||||
fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
|
||||
if let TyKind::Path(hir::QPath::Resolved(_, path)) =
|
||||
self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
|
||||
&& let Res::Def(def_kind, def_id) = path.res
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
if let Some((local_def_id, def_kind)) =
|
||||
adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty)
|
||||
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
|
||||
{
|
||||
if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
|
||||
@ -915,7 +927,7 @@ fn create_and_seed_worklist(
|
||||
match tcx.def_kind(id) {
|
||||
DefKind::Impl { .. } => false,
|
||||
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
|
||||
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
||||
DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
||||
_ => true
|
||||
})
|
||||
.map(|id| (id, ComesFromAllowExpect::No))
|
||||
|
@ -1448,7 +1448,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
);
|
||||
|
||||
if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
|
||||
err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span });
|
||||
let label_span = ident.span.shrink_to_hi();
|
||||
let mut spans = MultiSpan::from_span(label_span);
|
||||
spans.push_span_label(label_span, "put a macro name here");
|
||||
err.subdiagnostic(MaybeMissingMacroRulesName { spans: spans });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -669,7 +669,7 @@ pub(crate) struct MacroSuggMovePosition {
|
||||
#[note(resolve_missing_macro_rules_name)]
|
||||
pub(crate) struct MaybeMissingMacroRulesName {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) spans: MultiSpan,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
@ -557,6 +557,7 @@ symbols! {
|
||||
clobber_abi,
|
||||
clone,
|
||||
clone_closures,
|
||||
clone_fn,
|
||||
clone_from,
|
||||
closure,
|
||||
closure_lifetime_binder,
|
||||
|
@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
|
||||
self.has_type_flags(TypeFlags::HAS_ALIAS)
|
||||
}
|
||||
|
||||
fn has_inherent_projections(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_TY_INHERENT)
|
||||
}
|
||||
|
||||
fn has_opaque_types(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
|
||||
}
|
||||
|
@ -160,6 +160,9 @@ pub trait Clone: Sized {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "cloning is often expensive and is not expected to have side effects"]
|
||||
// Clone::clone is special because the compiler generates MIR to implement it for some types.
|
||||
// See InstanceKind::CloneShim.
|
||||
#[cfg_attr(not(bootstrap), lang = "clone_fn")]
|
||||
fn clone(&self) -> Self;
|
||||
|
||||
/// Performs copy-assignment from `source`.
|
||||
|
@ -201,6 +201,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
||||
"only-wasm32-wasip1",
|
||||
"only-watchos",
|
||||
"only-windows",
|
||||
"only-windows-gnu",
|
||||
"only-x86",
|
||||
"only-x86_64",
|
||||
"only-x86_64-fortanix-unknown-sgx",
|
||||
|
@ -15,6 +15,13 @@ pub fn cc() -> Cc {
|
||||
Cc::new()
|
||||
}
|
||||
|
||||
/// Construct a new platform-specific CXX compiler invocation.
|
||||
/// CXX_DEFAULT_FLAGS is passed from compiletest.
|
||||
#[track_caller]
|
||||
pub fn cxx() -> Cc {
|
||||
Cc::new_cxx()
|
||||
}
|
||||
|
||||
/// A platform-specific C compiler invocation builder. The specific C compiler used is
|
||||
/// passed down from compiletest.
|
||||
#[derive(Debug)]
|
||||
@ -44,6 +51,22 @@ impl Cc {
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Construct a new platform-specific CXX compiler invocation.
|
||||
/// CXX_DEFAULT_FLAGS is passed from compiletest.
|
||||
#[track_caller]
|
||||
pub fn new_cxx() -> Self {
|
||||
let compiler = env_var("CXX");
|
||||
|
||||
let mut cmd = Command::new(compiler);
|
||||
|
||||
let default_cflags = env_var("CXX_DEFAULT_FLAGS");
|
||||
for flag in default_cflags.split(char::is_whitespace) {
|
||||
cmd.arg(flag);
|
||||
}
|
||||
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Specify path of the input file.
|
||||
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
self.cmd.arg(path.as_ref());
|
||||
|
@ -44,7 +44,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust
|
||||
|
||||
// These rely on external dependencies.
|
||||
pub use c_build::{build_native_dynamic_lib, build_native_static_lib};
|
||||
pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
|
||||
pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
|
||||
pub use clang::{clang, Clang};
|
||||
pub use htmldocck::htmldocck;
|
||||
pub use llvm::{
|
||||
|
@ -2,7 +2,6 @@ run-make/branch-protection-check-IBT/Makefile
|
||||
run-make/c-unwind-abi-catch-lib-panic/Makefile
|
||||
run-make/cat-and-grep-sanity-check/Makefile
|
||||
run-make/cdylib-dylib-linkage/Makefile
|
||||
run-make/compiler-rt-works-on-mingw/Makefile
|
||||
run-make/cross-lang-lto-clang/Makefile
|
||||
run-make/cross-lang-lto-pgo-smoketest/Makefile
|
||||
run-make/cross-lang-lto-upstream-rlibs/Makefile
|
||||
@ -10,18 +9,14 @@ run-make/cross-lang-lto/Makefile
|
||||
run-make/dep-info-doesnt-run-much/Makefile
|
||||
run-make/dep-info-spaces/Makefile
|
||||
run-make/dep-info/Makefile
|
||||
run-make/dump-ice-to-disk/Makefile
|
||||
run-make/emit-to-stdout/Makefile
|
||||
run-make/export-executable-symbols/Makefile
|
||||
run-make/extern-flag-disambiguates/Makefile
|
||||
run-make/extern-fn-reachable/Makefile
|
||||
run-make/fmt-write-bloat/Makefile
|
||||
run-make/foreign-double-unwind/Makefile
|
||||
run-make/foreign-exceptions/Makefile
|
||||
run-make/foreign-rust-exceptions/Makefile
|
||||
run-make/incr-add-rust-src-component/Makefile
|
||||
run-make/incr-foreign-head-span/Makefile
|
||||
run-make/interdependent-c-libraries/Makefile
|
||||
run-make/issue-35164/Makefile
|
||||
run-make/issue-36710/Makefile
|
||||
run-make/issue-47551/Makefile
|
||||
@ -42,7 +37,6 @@ run-make/native-link-modifier-bundle/Makefile
|
||||
run-make/native-link-modifier-whole-archive/Makefile
|
||||
run-make/no-alloc-shim/Makefile
|
||||
run-make/no-builtins-attribute/Makefile
|
||||
run-make/panic-abort-eh_frame/Makefile
|
||||
run-make/pdb-buildinfo-cl-cmd/Makefile
|
||||
run-make/pgo-gen-lto/Makefile
|
||||
run-make/pgo-indirect-call-promotion/Makefile
|
||||
|
@ -41,3 +41,8 @@ The setup for the `rmake.rs` version is a 3-stage process:
|
||||
|
||||
[`run_make_support`]: ../../src/tools/run-make-support
|
||||
[extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude
|
||||
|
||||
### Formatting
|
||||
|
||||
Note that files under `tests/` are not formatted by `./x fmt`,
|
||||
use `rustfmt tests/path/to/file.rs` to format a specific file if desired.
|
||||
|
@ -1,9 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# only-windows-gnu
|
||||
|
||||
all:
|
||||
$(CXX) foo.cpp -c -o $(TMPDIR)/foo.o
|
||||
$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
|
||||
$(RUSTC) foo.rs -lfoo -lstdc++
|
||||
$(call RUN,foo)
|
15
tests/run-make/compiler-rt-works-on-mingw/rmake.rs
Normal file
15
tests/run-make/compiler-rt-works-on-mingw/rmake.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// `compiler-rt` ("runtime") is a suite of LLVM features compatible with rustc.
|
||||
// After building it was enabled on Windows-gnu in #29874, this test is a basic smoke test to
|
||||
// check if building and linking to it can work at all.
|
||||
// See https://github.com/rust-lang/rust/pull/29478
|
||||
|
||||
//@ only-windows-gnu
|
||||
|
||||
use run_make_support::{cxx, is_msvc, llvm_ar, run, rustc, static_lib_name};
|
||||
|
||||
fn main() {
|
||||
cxx().input("foo.cpp").arg("-c").out_exe("foo.o").run();
|
||||
llvm_ar().obj_to_ar().output_input(static_lib_name("foo"), "foo.o").run();
|
||||
rustc().input("foo.rs").arg("-lfoo").arg("-lstdc++").run();
|
||||
run("foo");
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# ignore-windows
|
||||
|
||||
export RUSTC := $(RUSTC_ORIGINAL)
|
||||
export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
|
||||
export TMPDIR := $(TMPDIR)
|
||||
|
||||
all:
|
||||
bash check.sh
|
@ -1,64 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Default nightly behavior (write ICE to current directory)
|
||||
# FIXME(estebank): these are failing on CI, but passing locally.
|
||||
# $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default.log 2>&1
|
||||
# default=$(cat ./rustc-ice-*.txt | wc -l)
|
||||
# rm ./rustc-ice-*.txt
|
||||
|
||||
# Explicit directory set
|
||||
export RUSTC_ICE=$TMPDIR
|
||||
$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default-set.log 2>&1
|
||||
default_set=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
|
||||
content=$(cat $TMPDIR/rustc-ice-*.txt)
|
||||
# Ensure that the ICE dump path doesn't contain `:` because they cause problems on Windows
|
||||
windows_safe=$(echo rustc-ice-*.txt | grep ':')
|
||||
if [ ! -z "$windows_safe" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm $TMPDIR/rustc-ice-*.txt
|
||||
RUST_BACKTRACE=short $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-short.log 2>&1
|
||||
short=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
|
||||
rm $TMPDIR/rustc-ice-*.txt
|
||||
RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-full.log 2>&1
|
||||
full=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
|
||||
rm $TMPDIR/rustc-ice-*.txt
|
||||
|
||||
# Explicitly disabling ICE dump
|
||||
export RUSTC_ICE=0
|
||||
$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1
|
||||
should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt 2>/dev/null | wc -l)
|
||||
should_be_empty_dot=$(ls -l ./rustc-ice-*.txt 2>/dev/null | wc -l)
|
||||
|
||||
echo "#### ICE Dump content:"
|
||||
echo $content
|
||||
echo "#### default length:"
|
||||
echo $default
|
||||
echo "#### short length:"
|
||||
echo $short
|
||||
echo "#### default_set length:"
|
||||
echo $default_set
|
||||
echo "#### full length:"
|
||||
echo $full
|
||||
echo "#### should_be_empty_dot length:"
|
||||
echo $should_be_empty_dot
|
||||
echo "#### should_be_empty_tmp length:"
|
||||
echo $should_be_empty_tmp
|
||||
|
||||
## Verify that a the ICE dump file is created in the appropriate directories, that
|
||||
## their lengths are the same regardless of other backtrace configuration options,
|
||||
## that the file is not created when asked to (RUSTC_ICE=0) and that the file
|
||||
## contains at least part of the expected content.
|
||||
if [ $short -eq $default_set ] &&
|
||||
#[ $default -eq $short ] &&
|
||||
[ $default_set -eq $full ] &&
|
||||
[[ $content == *"thread 'rustc' panicked at "* ]] &&
|
||||
[[ $content == *"stack backtrace:"* ]] &&
|
||||
#[ $default -gt 0 ] &&
|
||||
[ $should_be_empty_dot -eq 0 ] &&
|
||||
[ $should_be_empty_tmp -eq 0 ]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
81
tests/run-make/dump-ice-to-disk/rmake.rs
Normal file
81
tests/run-make/dump-ice-to-disk/rmake.rs
Normal file
@ -0,0 +1,81 @@
|
||||
// This test checks if internal compilation error (ICE) log files work as expected.
|
||||
// - Get the number of lines from the log files without any configuration options,
|
||||
// then check that the line count doesn't change if the backtrace gets configured to be short
|
||||
// or full.
|
||||
// - Check that disabling ICE logging results in zero files created.
|
||||
// - Check that the ICE files contain some of the expected strings.
|
||||
// See https://github.com/rust-lang/rust/pull/108714
|
||||
|
||||
use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files};
|
||||
|
||||
fn main() {
|
||||
rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
|
||||
let default = get_text_from_ice(".").lines().count();
|
||||
clear_ice_files();
|
||||
|
||||
rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
|
||||
let ice_text = get_text_from_ice(cwd());
|
||||
let default_set = ice_text.lines().count();
|
||||
let content = ice_text;
|
||||
let ice_files = shallow_find_files(cwd(), |path| {
|
||||
has_prefix(path, "rustc-ice") && has_extension(path, "txt")
|
||||
});
|
||||
assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
|
||||
let ice_file_name =
|
||||
ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap();
|
||||
// Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows.
|
||||
assert!(!ice_file_name.contains(":"), "{ice_file_name}");
|
||||
|
||||
clear_ice_files();
|
||||
rustc()
|
||||
.env("RUSTC_ICE", cwd())
|
||||
.input("lib.rs")
|
||||
.env("RUST_BACKTRACE", "short")
|
||||
.arg("-Ztreat-err-as-bug=1")
|
||||
.run_fail();
|
||||
let short = get_text_from_ice(cwd()).lines().count();
|
||||
clear_ice_files();
|
||||
rustc()
|
||||
.env("RUSTC_ICE", cwd())
|
||||
.input("lib.rs")
|
||||
.env("RUST_BACKTRACE", "full")
|
||||
.arg("-Ztreat-err-as-bug=1")
|
||||
.run_fail();
|
||||
let full = get_text_from_ice(cwd()).lines().count();
|
||||
clear_ice_files();
|
||||
|
||||
// The ICE dump is explicitly disabled. Therefore, this should produce no files.
|
||||
rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
|
||||
let ice_files = shallow_find_files(cwd(), |path| {
|
||||
has_prefix(path, "rustc-ice") && has_extension(path, "txt")
|
||||
});
|
||||
assert!(ice_files.is_empty()); // There should be 0 ICE files.
|
||||
|
||||
// The line count should not change.
|
||||
assert_eq!(short, default_set);
|
||||
assert_eq!(short, default);
|
||||
assert_eq!(full, default_set);
|
||||
assert!(default > 0);
|
||||
// Some of the expected strings in an ICE file should appear.
|
||||
assert!(content.contains("thread 'rustc' panicked at"));
|
||||
assert!(content.contains("stack backtrace:"));
|
||||
}
|
||||
|
||||
fn clear_ice_files() {
|
||||
let ice_files = shallow_find_files(cwd(), |path| {
|
||||
has_prefix(path, "rustc-ice") && has_extension(path, "txt")
|
||||
});
|
||||
for file in ice_files {
|
||||
rfs::remove_file(file);
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_text_from_ice(dir: impl AsRef<std::path::Path>) -> String {
|
||||
let ice_files =
|
||||
shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt"));
|
||||
assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
|
||||
let ice_file = ice_files.get(0).unwrap();
|
||||
let output = rfs::read_to_string(ice_file);
|
||||
output
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
# Attempt to build this dependency tree:
|
||||
#
|
||||
# A.1 A.2
|
||||
# |\ |
|
||||
# | \ |
|
||||
# B \ C
|
||||
# \ | /
|
||||
# \|/
|
||||
# D
|
||||
#
|
||||
# Note that A.1 and A.2 are crates with the same name.
|
||||
|
||||
all:
|
||||
$(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs
|
||||
$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
|
||||
$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
|
||||
@echo before
|
||||
$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(call RUN,d)
|
||||
@echo after
|
||||
$(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(call RUN,d)
|
30
tests/run-make/extern-flag-disambiguates/rmake.rs
Normal file
30
tests/run-make/extern-flag-disambiguates/rmake.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//@ ignore-cross-compile
|
||||
|
||||
use run_make_support::{cwd, run, rustc};
|
||||
|
||||
// Attempt to build this dependency tree:
|
||||
//
|
||||
// A.1 A.2
|
||||
// |\ |
|
||||
// | \ |
|
||||
// B \ C
|
||||
// \ | /
|
||||
// \|/
|
||||
// D
|
||||
//
|
||||
// Note that A.1 and A.2 are crates with the same name.
|
||||
|
||||
// original Makefile at https://github.com/rust-lang/rust/issues/14469
|
||||
|
||||
fn main() {
|
||||
rustc().metadata("1").extra_filename("-1").input("a.rs").run();
|
||||
rustc().metadata("2").extra_filename("-2").input("a.rs").run();
|
||||
rustc().input("b.rs").extern_("a", "liba-1.rlib").run();
|
||||
rustc().input("c.rs").extern_("a", "liba-2.rlib").run();
|
||||
println!("before");
|
||||
rustc().cfg("before").input("d.rs").extern_("a", "liba-1.rlib").run();
|
||||
run("d");
|
||||
println!("after");
|
||||
rustc().cfg("after").input("d.rs").extern_("a", "liba-1.rlib").run();
|
||||
run("d");
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# ignore-none no-std is not supported
|
||||
# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
|
||||
|
||||
# Ensure that modifying a crate on disk (without recompiling it)
|
||||
# does not cause ICEs in downstream crates.
|
||||
# Previously, we would call `SourceMap.guess_head_span` on a span
|
||||
# from an external crate, which would cause us to read an upstream
|
||||
# source file from disk during compilation of a downstream crate
|
||||
# See #86480 for more details
|
||||
|
||||
INCR=$(TMPDIR)/incr
|
||||
|
||||
all:
|
||||
cp first_crate.rs second_crate.rs $(TMPDIR)
|
||||
$(RUSTC) $(TMPDIR)/first_crate.rs -C incremental=$(INCR) --target $(TARGET) --crate-type lib
|
||||
$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first_crate=$(TMPDIR)/libfirst_crate.rlib --crate-type lib
|
||||
rm $(TMPDIR)/first_crate.rs
|
||||
$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
|
||||
|
25
tests/run-make/incr-foreign-head-span/rmake.rs
Normal file
25
tests/run-make/incr-foreign-head-span/rmake.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Ensure that modifying a crate on disk (without recompiling it)
|
||||
// does not cause ICEs (internal compiler errors) in downstream crates.
|
||||
// Previously, we would call `SourceMap.guess_head_span` on a span
|
||||
// from an external crate, which would cause us to read an upstream
|
||||
// source file from disk during compilation of a downstream crate.
|
||||
// See https://github.com/rust-lang/rust/issues/86480
|
||||
|
||||
//@ ignore-none
|
||||
// Reason: no-std is not supported
|
||||
//@ ignore-nvptx64-nvidia-cuda
|
||||
// Reason: can't find crate for 'std'
|
||||
|
||||
use run_make_support::{rfs, rust_lib_name, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("first_crate.rs").incremental("incr").crate_type("lib").run();
|
||||
rustc()
|
||||
.input("second_crate.rs")
|
||||
.incremental("incr")
|
||||
.extern_("first_crate", rust_lib_name("first_crate"))
|
||||
.crate_type("lib")
|
||||
.run();
|
||||
rfs::remove_file("first_crate.rs");
|
||||
rustc().input("second_crate.rs").incremental("incr").cfg("second_run").crate_type("lib").run();
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
# The rust crate foo will link to the native library foo, while the rust crate
|
||||
# bar will link to the native library bar. There is also a dependency between
|
||||
# the native library bar to the natibe library foo.
|
||||
#
|
||||
# This test ensures that the ordering of -lfoo and -lbar on the command line is
|
||||
# correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo'
|
||||
# library will be stripped out, and the linkage will fail.
|
||||
|
||||
all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
$(RUSTC) main.rs --print link-args
|
21
tests/run-make/interdependent-c-libraries/rmake.rs
Normal file
21
tests/run-make/interdependent-c-libraries/rmake.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// The rust crate foo will link to the native library foo, while the rust crate
|
||||
// bar will link to the native library bar. There is also a dependency between
|
||||
// the native library bar to the natibe library foo.
|
||||
// This test ensures that the ordering of -lfoo and -lbar on the command line is
|
||||
// correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo'
|
||||
// library will be stripped out, and the linkage will fail.
|
||||
// See https://github.com/rust-lang/rust/commit/e6072fa0c4c22d62acf3dcb78c8ee260a1368bd7
|
||||
|
||||
//@ ignore-cross-compile
|
||||
// Reason: linkage still fails as the object files produced are not in the correct
|
||||
// format in the `build_native_static_lib` step
|
||||
|
||||
use run_make_support::{build_native_static_lib, rustc};
|
||||
|
||||
fn main() {
|
||||
build_native_static_lib("foo");
|
||||
build_native_static_lib("bar");
|
||||
rustc().input("foo.rs").run();
|
||||
rustc().input("bar.rs").run();
|
||||
rustc().input("main.rs").print("link-args").run();
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# only-linux
|
||||
#
|
||||
# This test ensures that `panic=abort` code (without `C-unwind`, that is) should not have any
|
||||
# unwinding related `.eh_frame` sections emitted.
|
||||
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort --edition 2021 -Z validate-mir
|
||||
objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA'
|
24
tests/run-make/panic-abort-eh_frame/rmake.rs
Normal file
24
tests/run-make/panic-abort-eh_frame/rmake.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// An `.eh_frame` section in an object file is a symptom of an UnwindAction::Terminate
|
||||
// being inserted, useful for determining whether or not unwinding is necessary.
|
||||
// This is useless when panics would NEVER unwind due to -C panic=abort. This section should
|
||||
// therefore never appear in the emit file of a -C panic=abort compilation, and this test
|
||||
// checks that this is respected.
|
||||
// See https://github.com/rust-lang/rust/pull/112403
|
||||
|
||||
//@ only-linux
|
||||
// FIXME(Oneirical): the DW_CFA symbol appears on Windows-gnu, because uwtable
|
||||
// is forced to true on Windows targets (see #128136).
|
||||
|
||||
use run_make_support::{llvm_objdump, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc()
|
||||
.input("foo.rs")
|
||||
.crate_type("lib")
|
||||
.emit("obj=foo.o")
|
||||
.panic("abort")
|
||||
.edition("2021")
|
||||
.arg("-Zvalidate-mir")
|
||||
.run();
|
||||
llvm_objdump().arg("--dwarf=frames").input("foo.o").run().assert_stdout_not_contains("DW_CFA");
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
//@ compile-flags: --crate-type=lib
|
||||
//@ check-pass
|
||||
|
||||
#![feature(inherent_associated_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// Bounds on the self type play a major role in the resolution of inherent associated types (*).
|
||||
// As a result of that, if a type alias contains any then its bounds have to be respected and the
|
||||
// lint `type_alias_bounds` should not fire.
|
||||
|
||||
#![deny(type_alias_bounds)]
|
||||
|
||||
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||
|
||||
pub struct Source<T>(T);
|
||||
pub trait Bound {}
|
||||
|
||||
impl<T: Bound> Source<T> {
|
||||
pub type Assoc = ();
|
||||
}
|
29
tests/ui/associated-inherent-types/type-alias-bounds.rs
Normal file
29
tests/ui/associated-inherent-types/type-alias-bounds.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//@ compile-flags: --crate-type=lib
|
||||
//@ check-pass
|
||||
|
||||
#![feature(inherent_associated_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// FIXME(inherent_associated_types):
|
||||
// While we currently do take some clauses of the ParamEnv into consideration
|
||||
// when performing IAT selection, we do not perform full well-formedness checking
|
||||
// for (eager) type alias definition and usage sites.
|
||||
//
|
||||
// Therefore it's *correct* for lint `type_alias_bounds` to fire here despite the
|
||||
// fact that removing `Bound` from `T` in `Alias` would lead to an error!
|
||||
//
|
||||
// Obviously, the present situation isn't ideal and we should fix it in one way
|
||||
// or another. Either we somehow delay IAT selection until after HIR ty lowering
|
||||
// to avoid the need to specify any bounds inside (eager) type aliases or we
|
||||
// force the overarching type alias to be *lazy* (similar to TAITs) which would
|
||||
// automatically lead to full wfchecking and lint TAB getting suppressed.
|
||||
|
||||
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||
//~^ WARN bounds on generic parameters in type aliases are not enforced
|
||||
|
||||
pub struct Source<T>(T);
|
||||
pub trait Bound {}
|
||||
|
||||
impl<T: Bound> Source<T> {
|
||||
pub type Assoc = ();
|
||||
}
|
16
tests/ui/associated-inherent-types/type-alias-bounds.stderr
Normal file
16
tests/ui/associated-inherent-types/type-alias-bounds.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:21:19
|
||||
|
|
||||
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||
| --^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -1,147 +1,159 @@
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:3:25
|
||||
|
|
||||
LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
|
||||
LL + type _TaWhere1<T> = T;
|
||||
|
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:4:25
|
||||
|
|
||||
LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
|
||||
LL + type _TaWhere2<T> = T;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:5:25
|
||||
|
|
||||
LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
|
||||
LL + type _TaWhere3<T> = T;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:6:25
|
||||
|
|
||||
LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
|
||||
LL + type _TaWhere4<T> = T;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:7:25
|
||||
|
|
||||
LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
|
||||
LL + type _TaWhere5<T> = T;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:8:25
|
||||
|
|
||||
LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
|
||||
LL + type _TaWhere6<T> = T;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:10:20
|
||||
|
|
||||
LL | type _TaInline1<T: Iterator<Item: Copy>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline1<T: Iterator<Item: Copy>> = T;
|
||||
LL + type _TaInline1<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:11:20
|
||||
|
|
||||
LL | type _TaInline2<T: Iterator<Item: 'static>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline2<T: Iterator<Item: 'static>> = T;
|
||||
LL + type _TaInline2<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:12:20
|
||||
|
|
||||
LL | type _TaInline3<T: Iterator<Item: 'static>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline3<T: Iterator<Item: 'static>> = T;
|
||||
LL + type _TaInline3<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:13:20
|
||||
|
|
||||
LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
|
||||
LL + type _TaInline4<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:14:20
|
||||
|
|
||||
LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
|
||||
LL + type _TaInline5<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias.rs:15:20
|
||||
|
|
||||
LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
|
||||
LL + type _TaInline6<T> = T;
|
||||
| --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: 12 warnings emitted
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/type-alias-bounds.rs:23:12
|
||||
|
|
||||
LL | let _: AliasConstUnused<String>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `ct_unused_0::AliasConstUnused`
|
||||
--> $DIR/type-alias-bounds.rs:20:30
|
||||
|
|
||||
LL | type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>);
|
||||
| ^^^^ required by this bound in `AliasConstUnused`
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/type-alias-bounds.rs:31:12
|
||||
|
|
||||
LL | let _: AliasConstUnused;
|
||||
| ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `ct_unused_1::AliasConstUnused`
|
||||
--> $DIR/type-alias-bounds.rs:29:41
|
||||
|
|
||||
LL | type AliasConstUnused where String: Copy = I32<{ 0; 0 }>;
|
||||
| ^^^^ required by this bound in `AliasConstUnused`
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/type-alias-bounds.rs:39:12
|
||||
|
|
||||
LL | let _: AliasFnUnused<String>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `AliasFnUnused`
|
||||
--> $DIR/type-alias-bounds.rs:36:27
|
||||
|
|
||||
LL | type AliasFnUnused<T: Copy> = (T, I32<{ code() }>);
|
||||
| ^^^^ required by this bound in `AliasFnUnused`
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/type-alias-bounds.rs:57:12
|
||||
|
|
||||
LL | let _: AliasAssocConstUsed<String>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `AliasAssocConstUsed`
|
||||
--> $DIR/type-alias-bounds.rs:55:41
|
||||
|
|
||||
LL | type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>;
|
||||
| ^^^^ required by this bound in `AliasAssocConstUsed`
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/type-alias-bounds.rs:65:12
|
||||
|
|
||||
LL | let _: AliasFnUsed<String>;
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required by a bound in `AliasFnUsed`
|
||||
--> $DIR/type-alias-bounds.rs:62:33
|
||||
|
|
||||
LL | type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>;
|
||||
| ^^^^ required by this bound in `AliasFnUsed`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,71 @@
|
||||
//@ revisions: pos neg
|
||||
//@[pos] check-pass
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(trivial_bounds)] // only used in test case `ct_unused_1`
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// FIXME(generic_const_exprs): Revisit this before stabilization.
|
||||
// Check that we don't emit the lint `type_alias_bounds` for (eager) type aliases
|
||||
// whose RHS contains a const projection (aka uneval'ed const).
|
||||
// Since anon consts inherit the parent generics and predicates and we effectively
|
||||
// check them before and after instantiaton for well-formedness, the type alias
|
||||
// bounds are in every sense "enforced".
|
||||
// Note that the test cases whose name ends in "unused" just demonstrate that this
|
||||
// holds even if the const projections don't "visibly" capture any generics and/or
|
||||
// predicates.
|
||||
#![deny(type_alias_bounds)]
|
||||
|
||||
fn ct_unused_0() {
|
||||
type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>);
|
||||
const DATA: i32 = 0;
|
||||
#[cfg(neg)]
|
||||
let _: AliasConstUnused<String>;
|
||||
//[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn ct_unused_1() {
|
||||
#[allow(trivial_bounds)]
|
||||
type AliasConstUnused where String: Copy = I32<{ 0; 0 }>;
|
||||
#[cfg(neg)]
|
||||
let _: AliasConstUnused;
|
||||
//[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn fn_unused() {
|
||||
type AliasFnUnused<T: Copy> = (T, I32<{ code() }>);
|
||||
const fn code() -> i32 { 0 }
|
||||
#[cfg(neg)]
|
||||
let _: AliasFnUnused<String>;
|
||||
//[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
type Proj;
|
||||
const DATA: i32;
|
||||
}
|
||||
|
||||
impl Trait for String {
|
||||
type Proj = i32;
|
||||
const DATA: i32 = 0;
|
||||
}
|
||||
|
||||
// Regression test for issue #94398.
|
||||
fn assoc_ct_used() {
|
||||
type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>;
|
||||
#[cfg(neg)]
|
||||
let _: AliasAssocConstUsed<String>;
|
||||
//[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn fn_used() {
|
||||
type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>;
|
||||
const fn code<T: Trait>() -> i32 { T::DATA }
|
||||
#[cfg(neg)]
|
||||
let _: AliasFnUsed<String>;
|
||||
//[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
}
|
||||
|
||||
struct I32<const N: i32>;
|
||||
|
||||
fn main() {}
|
45
tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
Normal file
45
tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
Normal file
@ -0,0 +1,45 @@
|
||||
#![deny(dead_code)]
|
||||
|
||||
struct Foo; //~ ERROR struct `Foo` is never constructed
|
||||
|
||||
trait Trait { //~ ERROR trait `Trait` is never used
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
impl Trait for Foo {}
|
||||
|
||||
impl Trait for [Foo] {}
|
||||
impl<const N: usize> Trait for [Foo; N] {}
|
||||
|
||||
impl Trait for *const Foo {}
|
||||
impl Trait for *mut Foo {}
|
||||
|
||||
impl Trait for &Foo {}
|
||||
impl Trait for &&Foo {}
|
||||
impl Trait for &mut Foo {}
|
||||
|
||||
impl Trait for [&Foo] {}
|
||||
impl Trait for &[Foo] {}
|
||||
impl Trait for &*const Foo {}
|
||||
|
||||
pub trait Trait2 {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
impl Trait2 for Foo {}
|
||||
|
||||
impl Trait2 for [Foo] {}
|
||||
impl<const N: usize> Trait2 for [Foo; N] {}
|
||||
|
||||
impl Trait2 for *const Foo {}
|
||||
impl Trait2 for *mut Foo {}
|
||||
|
||||
impl Trait2 for &Foo {}
|
||||
impl Trait2 for &&Foo {}
|
||||
impl Trait2 for &mut Foo {}
|
||||
|
||||
impl Trait2 for [&Foo] {}
|
||||
impl Trait2 for &[Foo] {}
|
||||
impl Trait2 for &*const Foo {}
|
||||
|
||||
fn main() {}
|
20
tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
Normal file
20
tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error: struct `Foo` is never constructed
|
||||
--> $DIR/unused-impl-for-non-adts.rs:3:8
|
||||
|
|
||||
LL | struct Foo;
|
||||
| ^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused-impl-for-non-adts.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: trait `Trait` is never used
|
||||
--> $DIR/unused-impl-for-non-adts.rs:5:7
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -7,6 +7,7 @@ macro_rules! make_macro {
|
||||
macro_rules! $macro_name {
|
||||
//~^ ERROR macro expansion ignores token `{` and any following
|
||||
//~| ERROR cannot find macro `macro_rules` in this scope
|
||||
//~| put a macro name here
|
||||
() => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
--> $DIR/issue-118786.rs:15:13
|
||||
--> $DIR/issue-118786.rs:16:13
|
||||
|
|
||||
LL | make_macro!((meow));
|
||||
| ^^^^^^
|
||||
@ -34,10 +34,10 @@ LL | make_macro!((meow));
|
||||
| ------------------- in this macro invocation
|
||||
|
|
||||
note: maybe you have forgotten to define a name for this `macro_rules!`
|
||||
--> $DIR/issue-118786.rs:7:9
|
||||
--> $DIR/issue-118786.rs:7:20
|
||||
|
|
||||
LL | macro_rules! $macro_name {
|
||||
| ^^^^^^^^^^^
|
||||
| ^ put a macro name here
|
||||
...
|
||||
LL | make_macro!((meow));
|
||||
| ------------------- in this macro invocation
|
||||
|
@ -39,7 +39,7 @@ mod traits {
|
||||
pub trait PubTr {}
|
||||
|
||||
pub type Alias<T: PrivTr> = T; //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Alias`
|
||||
//~^ WARNING bounds on generic parameters are not enforced in type aliases
|
||||
//~^ WARNING bounds on generic parameters in type aliases are not enforced
|
||||
pub trait Tr1: PrivTr {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr1`
|
||||
pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr2`
|
||||
pub trait Tr3 {
|
||||
@ -58,7 +58,7 @@ mod traits_where {
|
||||
|
||||
pub type Alias<T> where T: PrivTr = T;
|
||||
//~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Alias`
|
||||
//~| WARNING where clauses are not enforced in type aliases
|
||||
//~| WARNING where clauses on type aliases are not enforced
|
||||
pub trait Tr2<T> where T: PrivTr {}
|
||||
//~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2`
|
||||
pub trait Tr3 {
|
||||
|
@ -395,30 +395,32 @@ note: but type `Priv2` is only usable at visibility `pub(self)`
|
||||
LL | struct Priv2;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/private-in-public-warn.rs:41:23
|
||||
|
|
||||
LL | pub type Alias<T: PrivTr> = T;
|
||||
| ^^^^^^
|
||||
| --^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - pub type Alias<T: PrivTr> = T;
|
||||
LL + pub type Alias<T> = T;
|
||||
|
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/private-in-public-warn.rs:59:29
|
||||
|
|
||||
LL | pub type Alias<T> where T: PrivTr = T;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - pub type Alias<T> where T: PrivTr = T;
|
||||
LL + pub type Alias<T> = T;
|
||||
| ------^^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
error: aborting due to 34 previous errors; 2 warnings emitted
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
macro_rules! {}
|
||||
//~^ ERROR cannot find macro `macro_rules` in this scope
|
||||
//~| NOTE maybe you have forgotten to define a name for this `macro_rules!`
|
||||
//~| put a macro name here
|
||||
|
||||
macro_rules!{}
|
||||
//~^ ERROR cannot find macro `macro_rules` in this scope
|
||||
//~| NOTE maybe you have forgotten to define a name for this `macro_rules!`
|
||||
//~| put a macro name here
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,3 +1,15 @@
|
||||
error: cannot find macro `macro_rules` in this scope
|
||||
--> $DIR/issue-118295.rs:6:1
|
||||
|
|
||||
LL | macro_rules!{}
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: maybe you have forgotten to define a name for this `macro_rules!`
|
||||
--> $DIR/issue-118295.rs:6:12
|
||||
|
|
||||
LL | macro_rules!{}
|
||||
| ^ put a macro name here
|
||||
|
||||
error: cannot find macro `macro_rules` in this scope
|
||||
--> $DIR/issue-118295.rs:1:1
|
||||
|
|
||||
@ -5,10 +17,10 @@ LL | macro_rules! {}
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: maybe you have forgotten to define a name for this `macro_rules!`
|
||||
--> $DIR/issue-118295.rs:1:1
|
||||
--> $DIR/issue-118295.rs:1:12
|
||||
|
|
||||
LL | macro_rules! {}
|
||||
| ^^^^^^^^^^^
|
||||
| ^ put a macro name here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -19,7 +19,7 @@ help: consider further restricting type parameter `T`
|
||||
|
|
||||
LL | T::Baa: std::fmt::Debug, T: Foo
|
||||
| ~~~~~~~~
|
||||
help: and also change the associated type name
|
||||
help: ...and changing the associated type name
|
||||
|
|
||||
LL | T::Bar: std::fmt::Debug,
|
||||
| ~~~
|
||||
|
@ -24,18 +24,19 @@ warning: trait bound i32: Foo does not depend on any type or lifetime parameters
|
||||
LL | union U where i32: Foo { f: i32 }
|
||||
| ^^^
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/trivial-bounds-inconsistent.rs:22:14
|
||||
|
|
||||
LL | type Y where i32: Foo = ();
|
||||
| ^^^^^^^^
|
||||
| ------^^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type Y where i32: Foo = ();
|
||||
LL + type Y = ();
|
||||
|
|
||||
|
||||
warning: trait bound i32: Foo does not depend on any type or lifetime parameters
|
||||
--> $DIR/trivial-bounds-inconsistent.rs:22:19
|
||||
|
@ -0,0 +1,36 @@
|
||||
error[E0220]: associated type `Assoc` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22
|
||||
|
|
||||
LL | type AssocOf<T> = T::Assoc;
|
||||
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
|
||||
|
|
||||
help: consider fully qualifying the associated type
|
||||
|
|
||||
LL | type AssocOf<T> = <T as Trait>::Assoc;
|
||||
| + +++++++++
|
||||
|
||||
error[E0220]: associated type `Assok` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22
|
||||
|
|
||||
LL | type AssokOf<T> = T::Assok;
|
||||
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
|
||||
|
|
||||
help: consider fully qualifying and renaming the associated type
|
||||
|
|
||||
LL | type AssokOf<T> = <T as Trait>::Assoc;
|
||||
| + +++++++++ ~~~~~
|
||||
|
||||
error[E0220]: associated type `Proj` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21
|
||||
|
|
||||
LL | type ProjOf<T> = T::Proj;
|
||||
| ^^^^ there is an associated type `Proj` in the trait `Parametrized`
|
||||
|
|
||||
help: consider fully qualifying the associated type
|
||||
|
|
||||
LL | type ProjOf<T> = <T as Parametrized</* 'a, T, N */>>::Proj;
|
||||
| + ++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0220`.
|
@ -0,0 +1,40 @@
|
||||
error[E0220]: associated type `Assoc` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22
|
||||
|
|
||||
LL | type AssocOf<T> = T::Assoc;
|
||||
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type AssocOf<T: Trait> = T::Assoc;
|
||||
| +++++++
|
||||
|
||||
error[E0220]: associated type `Assok` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22
|
||||
|
|
||||
LL | type AssokOf<T> = T::Assok;
|
||||
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type AssokOf<T: Trait> = T::Assok;
|
||||
| +++++++
|
||||
help: ...and changing the associated type name
|
||||
|
|
||||
LL | type AssokOf<T> = T::Assoc;
|
||||
| ~~~~~
|
||||
|
||||
error[E0220]: associated type `Proj` not found for `T`
|
||||
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21
|
||||
|
|
||||
LL | type ProjOf<T> = T::Proj;
|
||||
| ^^^^ there is an associated type `Proj` in the trait `Parametrized`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type ProjOf<T: Parametrized</* 'a, T, N */>> = T::Proj;
|
||||
| ++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0220`.
|
26
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
Normal file
26
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Ensure that we don't suggest *type alias bounds* for **eager** type aliases.
|
||||
// issue: rust-lang/rust#125789
|
||||
|
||||
//@ revisions: eager lazy
|
||||
#![cfg_attr(lazy, feature(lazy_type_alias), allow(incomplete_features))]
|
||||
|
||||
trait Trait { type Assoc; }
|
||||
|
||||
type AssocOf<T> = T::Assoc; //~ ERROR associated type `Assoc` not found for `T`
|
||||
//[eager]~^ HELP consider fully qualifying the associated type
|
||||
//[lazy]~| HELP consider restricting type parameter `T`
|
||||
|
||||
type AssokOf<T> = T::Assok; //~ ERROR associated type `Assok` not found for `T`
|
||||
//[eager]~^ HELP consider fully qualifying and renaming the associated type
|
||||
//[lazy]~| HELP consider restricting type parameter `T`
|
||||
//[lazy]~| HELP and changing the associated type name
|
||||
|
||||
trait Parametrized<'a, T, const N: usize> {
|
||||
type Proj;
|
||||
}
|
||||
|
||||
type ProjOf<T> = T::Proj; //~ ERROR associated type `Proj` not found for `T`
|
||||
//[eager]~^ HELP consider fully qualifying the associated type
|
||||
//[lazy]~| HELP consider restricting type parameter `T`
|
||||
|
||||
fn main() {}
|
@ -3,6 +3,6 @@
|
||||
|
||||
//@ check-pass
|
||||
pub type T<P: Send + Send + Send> = P;
|
||||
//~^ WARN bounds on generic parameters are not enforced in type aliases
|
||||
//~^ WARN bounds on generic parameters in type aliases are not enforced
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,15 +1,16 @@
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15
|
||||
|
|
||||
LL | pub type T<P: Send + Send + Send> = P;
|
||||
| ^^^^ ^^^^ ^^^^
|
||||
| --^^^^---^^^^---^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - pub type T<P: Send + Send + Send> = P;
|
||||
LL + pub type T<P> = P;
|
||||
|
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -6,15 +6,15 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
type SVec<T: Send + Send> = Vec<T>;
|
||||
//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
|
||||
//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
|
||||
type S2Vec<T> where T: Send = Vec<T>;
|
||||
//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
|
||||
//~^ WARN where clauses on type aliases are not enforced [type_alias_bounds]
|
||||
type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
|
||||
//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
|
||||
//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
|
||||
type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
|
||||
//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
|
||||
//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
|
||||
type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
|
||||
//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
|
||||
//~^ WARN where clauses on type aliases are not enforced [type_alias_bounds]
|
||||
|
||||
static STATIC: u32 = 0;
|
||||
|
||||
@ -42,10 +42,11 @@ fn foo<'a>(y: &'a i32) {
|
||||
struct Sendable<T: Send>(T);
|
||||
type MySendable<T> = Sendable<T>; // no error here!
|
||||
|
||||
// However, bounds *are* taken into account when accessing associated types
|
||||
// Bounds on type params do enable shorthand type alias paths.
|
||||
// However, that doesn't actually mean that they are properly enforced.
|
||||
trait Bound { type Assoc; }
|
||||
type T1<U: Bound> = U::Assoc; //~ WARN not enforced in type aliases
|
||||
type T2<U> where U: Bound = U::Assoc; //~ WARN not enforced in type aliases
|
||||
type T1<U: Bound> = U::Assoc; //~ WARN are not enforced
|
||||
type T2<U> where U: Bound = U::Assoc; //~ WARN are not enforced
|
||||
|
||||
// This errors:
|
||||
// `type T3<U> = U::Assoc;`
|
||||
@ -53,7 +54,7 @@ type T2<U> where U: Bound = U::Assoc; //~ WARN not enforced in type aliases
|
||||
type T4<U> = <U as Bound>::Assoc;
|
||||
|
||||
// Make sure the help about associated types is not shown incorrectly
|
||||
type T5<U: Bound> = <U as Bound>::Assoc; //~ WARN not enforced in type aliases
|
||||
type T6<U: Bound> = ::std::vec::Vec<U>; //~ WARN not enforced in type aliases
|
||||
type T5<U: Bound> = <U as Bound>::Assoc; //~ WARN are not enforced
|
||||
type T6<U: Bound> = ::std::vec::Vec<U>; //~ WARN are not enforced
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,121 +1,132 @@
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:8:14
|
||||
|
|
||||
LL | type SVec<T: Send + Send> = Vec<T>;
|
||||
| ^^^^ ^^^^
|
||||
| --^^^^---^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
= note: `#[warn(type_alias_bounds)]` on by default
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type SVec<T: Send + Send> = Vec<T>;
|
||||
LL + type SVec<T> = Vec<T>;
|
||||
|
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:10:21
|
||||
|
|
||||
LL | type S2Vec<T> where T: Send = Vec<T>;
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type S2Vec<T> where T: Send = Vec<T>;
|
||||
LL + type S2Vec<T> = Vec<T>;
|
||||
| ------^^^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:12:19
|
||||
|
|
||||
LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
|
||||
| ^^ ^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
|
||||
LL + type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
|
||||
| --^^---^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:14:18
|
||||
|
|
||||
LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
|
||||
| ^^ ^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
|
||||
LL + type WVec<'b, T> = (&'b u32, Vec<T>);
|
||||
| --^^---^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:16:25
|
||||
|
|
||||
LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
|
||||
| ^^^^^ ^^^^^
|
||||
|
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
|
||||
LL + type W2Vec<'b, T> = (&'b u32, Vec<T>);
|
||||
| ------^^^^^--^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this where clause
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:47:12
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:48:12
|
||||
|
|
||||
LL | type T1<U: Bound> = U::Assoc;
|
||||
| ^^^^^
|
||||
| ^^^^^ will not be checked at usage sites of the type alias
|
||||
|
|
||||
help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:47:21
|
||||
|
|
||||
LL | type T1<U: Bound> = U::Assoc;
|
||||
| ^^^^^^^^
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
help: remove this bound
|
||||
|
|
||||
LL - type T1<U: Bound> = U::Assoc;
|
||||
LL + type T1<U> = U::Assoc;
|
||||
|
|
||||
help: fully qualify this associated type
|
||||
|
|
||||
LL | type T1<U: Bound> = <U as /* Trait */>::Assoc;
|
||||
| + +++++++++++++++
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:48:18
|
||||
warning: where clauses on type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:49:18
|
||||
|
|
||||
LL | type T2<U> where U: Bound = U::Assoc;
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^^ will not be checked at usage sites of the type alias
|
||||
|
|
||||
help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:48:29
|
||||
|
|
||||
LL | type T2<U> where U: Bound = U::Assoc;
|
||||
| ^^^^^^^^
|
||||
help: the clause will not be checked when the type alias is used, and should be removed
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
help: remove this where clause
|
||||
|
|
||||
LL - type T2<U> where U: Bound = U::Assoc;
|
||||
LL + type T2<U> = U::Assoc;
|
||||
|
|
||||
help: fully qualify this associated type
|
||||
|
|
||||
LL | type T2<U> where U: Bound = <U as /* Trait */>::Assoc;
|
||||
| + +++++++++++++++
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:56:12
|
||||
|
|
||||
LL | type T5<U: Bound> = <U as Bound>::Assoc;
|
||||
| ^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type T5<U: Bound> = <U as Bound>::Assoc;
|
||||
LL + type T5<U> = <U as Bound>::Assoc;
|
||||
|
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:57:12
|
||||
|
|
||||
LL | type T5<U: Bound> = <U as Bound>::Assoc;
|
||||
| --^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: bounds on generic parameters in type aliases are not enforced
|
||||
--> $DIR/type-alias-bounds.rs:58:12
|
||||
|
|
||||
LL | type T6<U: Bound> = ::std::vec::Vec<U>;
|
||||
| ^^^^^
|
||||
|
|
||||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL - type T6<U: Bound> = ::std::vec::Vec<U>;
|
||||
LL + type T6<U> = ::std::vec::Vec<U>;
|
||||
| --^^^^^
|
||||
| | |
|
||||
| | will not be checked at usage sites of the type alias
|
||||
| help: remove this bound
|
||||
|
|
||||
= note: this is a known limitation of the type checker that may be lifted in a future edition.
|
||||
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
|
||||
|
||||
warning: 9 warnings emitted
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user