Auto merge of #123725 - GuillaumeGomez:rollup-gk2bbrg, r=GuillaumeGomez
Rollup of 7 pull requests Successful merges: - #118391 (Add `REDUNDANT_LIFETIMES` lint to detect lifetimes which are semantically redundant) - #123534 (Windows: set main thread name without re-encoding) - #123659 (Add support to intrinsics fallback body) - #123689 (Add const generics support for pattern types) - #123701 (Only assert for child/parent projection compatibility AFTER checking that theyre coming from the same place) - #123702 (Further cleanup cfgs in the UI test suite) - #123706 (rustdoc: reduce per-page HTML overhead) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5974fe87c4
50 changed files with 755 additions and 242 deletions
|
@ -46,6 +46,7 @@ impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! into_diag_arg_using_display {
|
macro_rules! into_diag_arg_using_display {
|
||||||
($( $ty:ty ),+ $(,)?) => {
|
($( $ty:ty ),+ $(,)?) => {
|
||||||
$(
|
$(
|
||||||
|
|
|
@ -355,6 +355,9 @@ hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pa
|
||||||
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
||||||
.label = not allowed in type signatures
|
.label = not allowed in type signatures
|
||||||
|
|
||||||
|
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
|
||||||
|
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
|
||||||
|
|
||||||
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
|
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
|
||||||
|
|
||||||
hir_analysis_return_type_notation_equality_bound =
|
hir_analysis_return_type_notation_equality_bound =
|
||||||
|
|
|
@ -8,11 +8,13 @@ use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
|
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::ItemKind;
|
use rustc_hir::ItemKind;
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||||
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||||
|
@ -136,6 +138,8 @@ where
|
||||||
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
|
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
|
||||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||||
|
|
||||||
|
lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);
|
||||||
|
|
||||||
let errors = infcx.resolve_regions(&outlives_env);
|
let errors = infcx.resolve_regions(&outlives_env);
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -2010,6 +2014,137 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lint_redundant_lifetimes<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
owner_id: LocalDefId,
|
||||||
|
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||||
|
) {
|
||||||
|
let def_kind = tcx.def_kind(owner_id);
|
||||||
|
match def_kind {
|
||||||
|
DefKind::Struct
|
||||||
|
| DefKind::Union
|
||||||
|
| DefKind::Enum
|
||||||
|
| DefKind::Trait
|
||||||
|
| DefKind::TraitAlias
|
||||||
|
| DefKind::Fn
|
||||||
|
| DefKind::Const
|
||||||
|
| DefKind::Impl { of_trait: _ } => {
|
||||||
|
// Proceed
|
||||||
|
}
|
||||||
|
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||||
|
let parent_def_id = tcx.local_parent(owner_id);
|
||||||
|
if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) {
|
||||||
|
// Don't check for redundant lifetimes for associated items of trait
|
||||||
|
// implementations, since the signature is required to be compatible
|
||||||
|
// with the trait, even if the implementation implies some lifetimes
|
||||||
|
// are redundant.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefKind::Mod
|
||||||
|
| DefKind::Variant
|
||||||
|
| DefKind::TyAlias
|
||||||
|
| DefKind::ForeignTy
|
||||||
|
| DefKind::TyParam
|
||||||
|
| DefKind::ConstParam
|
||||||
|
| DefKind::Static { .. }
|
||||||
|
| DefKind::Ctor(_, _)
|
||||||
|
| DefKind::Macro(_)
|
||||||
|
| DefKind::ExternCrate
|
||||||
|
| DefKind::Use
|
||||||
|
| DefKind::ForeignMod
|
||||||
|
| DefKind::AnonConst
|
||||||
|
| DefKind::InlineConst
|
||||||
|
| DefKind::OpaqueTy
|
||||||
|
| DefKind::Field
|
||||||
|
| DefKind::LifetimeParam
|
||||||
|
| DefKind::GlobalAsm
|
||||||
|
| DefKind::Closure => return,
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ordering of this lifetime map is a bit subtle.
|
||||||
|
//
|
||||||
|
// Specifically, we want to find a "candidate" lifetime that precedes a "victim" lifetime,
|
||||||
|
// where we can prove that `'candidate = 'victim`.
|
||||||
|
//
|
||||||
|
// `'static` must come first in this list because we can never replace `'static` with
|
||||||
|
// something else, but if we find some lifetime `'a` where `'a = 'static`, we want to
|
||||||
|
// suggest replacing `'a` with `'static`.
|
||||||
|
let mut lifetimes = vec![tcx.lifetimes.re_static];
|
||||||
|
lifetimes.extend(
|
||||||
|
ty::GenericArgs::identity_for_item(tcx, owner_id).iter().filter_map(|arg| arg.as_region()),
|
||||||
|
);
|
||||||
|
// If we are in a function, add its late-bound lifetimes too.
|
||||||
|
if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
|
||||||
|
for var in tcx.fn_sig(owner_id).instantiate_identity().bound_vars() {
|
||||||
|
let ty::BoundVariableKind::Region(kind) = var else { continue };
|
||||||
|
lifetimes.push(ty::Region::new_late_param(tcx, owner_id.to_def_id(), kind));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lifetimes.retain(|candidate| candidate.has_name());
|
||||||
|
|
||||||
|
// Keep track of lifetimes which have already been replaced with other lifetimes.
|
||||||
|
// This makes sure that if `'a = 'b = 'c`, we don't say `'c` should be replaced by
|
||||||
|
// both `'a` and `'b`.
|
||||||
|
let mut shadowed = FxHashSet::default();
|
||||||
|
|
||||||
|
for (idx, &candidate) in lifetimes.iter().enumerate() {
|
||||||
|
// Don't suggest removing a lifetime twice. We only need to check this
|
||||||
|
// here and not up in the `victim` loop because equality is transitive,
|
||||||
|
// so if A = C and B = C, then A must = B, so it'll be shadowed too in
|
||||||
|
// A's victim loop.
|
||||||
|
if shadowed.contains(&candidate) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for &victim in &lifetimes[(idx + 1)..] {
|
||||||
|
// We should only have late-bound lifetimes of the `BrNamed` variety,
|
||||||
|
// since we get these signatures straight from `hir_lowering`. And any
|
||||||
|
// other regions (ReError/ReStatic/etc.) shouldn't matter, since we
|
||||||
|
// can't really suggest to remove them.
|
||||||
|
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||||
|
| ty::ReLateParam(ty::LateParamRegion {
|
||||||
|
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||||
|
..
|
||||||
|
})) = victim.kind()
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Do not rename lifetimes not local to this item since they'll overlap
|
||||||
|
// with the lint running on the parent. We still want to consider parent
|
||||||
|
// lifetimes which make child lifetimes redundant, otherwise we would
|
||||||
|
// have truncated the `identity_for_item` args above.
|
||||||
|
if tcx.parent(def_id) != owner_id.to_def_id() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If `candidate <: victim` and `victim <: candidate`, then they're equal.
|
||||||
|
if outlives_env.free_region_map().sub_free_regions(tcx, candidate, victim)
|
||||||
|
&& outlives_env.free_region_map().sub_free_regions(tcx, victim, candidate)
|
||||||
|
{
|
||||||
|
shadowed.insert(victim);
|
||||||
|
tcx.emit_node_span_lint(
|
||||||
|
rustc_lint_defs::builtin::REDUNDANT_LIFETIMES,
|
||||||
|
tcx.local_def_id_to_hir_id(def_id.expect_local()),
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
RedundantLifetimeArgsLint { candidate, victim },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(hir_analysis_redundant_lifetime_args)]
|
||||||
|
#[note]
|
||||||
|
struct RedundantLifetimeArgsLint<'tcx> {
|
||||||
|
/// The lifetime we have found to be redundant.
|
||||||
|
victim: ty::Region<'tcx>,
|
||||||
|
// The lifetime we can replace the victim with.
|
||||||
|
candidate: ty::Region<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
|
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::resolve_bound_vars::*;
|
use rustc_middle::middle::resolve_bound_vars::*;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||||
use rustc_session::lint;
|
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -867,31 +866,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
}) => {
|
}) => {
|
||||||
self.visit_lifetime(lifetime);
|
self.visit_lifetime(lifetime);
|
||||||
walk_list!(self, visit_param_bound, bounds);
|
walk_list!(self, visit_param_bound, bounds);
|
||||||
|
|
||||||
if lifetime.res != hir::LifetimeName::Static {
|
|
||||||
for bound in bounds {
|
|
||||||
let hir::GenericBound::Outlives(lt) = bound else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if lt.res != hir::LifetimeName::Static {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
|
|
||||||
self.tcx.node_span_lint(
|
|
||||||
lint::builtin::UNUSED_LIFETIMES,
|
|
||||||
lifetime.hir_id,
|
|
||||||
lifetime.ident.span,
|
|
||||||
format!("unnecessary lifetime parameter `{}`", lifetime.ident),
|
|
||||||
|lint| {
|
|
||||||
let help = format!(
|
|
||||||
"you can use the `'static` lifetime directly, in place of `{}`",
|
|
||||||
lifetime.ident,
|
|
||||||
);
|
|
||||||
lint.help(help);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
|
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
|
||||||
self.visit_ty(lhs_ty);
|
self.visit_ty(lhs_ty);
|
||||||
|
|
|
@ -2223,6 +2223,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
Err(LitToConstError::TypeError) => todo!(),
|
Err(LitToConstError::TypeError) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
|
_,
|
||||||
|
&hir::Path {
|
||||||
|
res: Res::Def(DefKind::ConstParam, def_id), ..
|
||||||
|
},
|
||||||
|
)) => {
|
||||||
|
let ty = tcx
|
||||||
|
.type_of(def_id)
|
||||||
|
.no_bound_vars()
|
||||||
|
.expect("const parameter types cannot be generic");
|
||||||
|
let item_def_id = tcx.parent(def_id);
|
||||||
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty)
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let err = tcx
|
let err = tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
|
|
|
@ -79,6 +79,7 @@ declare_lint_pass! {
|
||||||
PROC_MACRO_BACK_COMPAT,
|
PROC_MACRO_BACK_COMPAT,
|
||||||
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||||
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
||||||
|
REDUNDANT_LIFETIMES,
|
||||||
REFINING_IMPL_TRAIT_INTERNAL,
|
REFINING_IMPL_TRAIT_INTERNAL,
|
||||||
REFINING_IMPL_TRAIT_REACHABLE,
|
REFINING_IMPL_TRAIT_REACHABLE,
|
||||||
RENAMED_AND_REMOVED_LINTS,
|
RENAMED_AND_REMOVED_LINTS,
|
||||||
|
@ -1707,6 +1708,33 @@ declare_lint! {
|
||||||
"detects lifetime parameters that are never used"
|
"detects lifetime parameters that are never used"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `redundant_lifetimes` lint detects lifetime parameters that are
|
||||||
|
/// redundant because they are equal to another named lifetime.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust,compile_fail
|
||||||
|
/// #[deny(redundant_lifetimes)]
|
||||||
|
///
|
||||||
|
/// // `'a = 'static`, so all usages of `'a` can be replaced with `'static`
|
||||||
|
/// pub fn bar<'a: 'static>() {}
|
||||||
|
///
|
||||||
|
/// // `'a = 'b`, so all usages of `'b` can be replaced with `'a`
|
||||||
|
/// pub fn bar<'a: 'b, 'b: 'a>() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// Unused lifetime parameters may signal a mistake or unfinished code.
|
||||||
|
/// Consider removing the parameter.
|
||||||
|
pub REDUNDANT_LIFETIMES,
|
||||||
|
Allow,
|
||||||
|
"detects lifetime parameters that are redundant because they are equal to some other named lifetime"
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `tyvar_behind_raw_pointer` lint detects raw pointer to an
|
/// The `tyvar_behind_raw_pointer` lint detects raw pointer to an
|
||||||
/// inference variable.
|
/// inference variable.
|
||||||
|
|
|
@ -757,7 +757,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
impl<'tcx> GlobalCtxt<'tcx> {
|
impl<'tcx> GlobalCtxt<'tcx> {
|
||||||
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
|
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
|
||||||
/// `f`.
|
/// `f`.
|
||||||
pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
|
pub fn enter<F, R>(&'tcx self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(TyCtxt<'tcx>) -> R,
|
F: FnOnce(TyCtxt<'tcx>) -> R,
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,13 +5,13 @@ use std::fmt::Write;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque, PolyTraitPredicate,
|
self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque,
|
||||||
Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
|
PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
|
||||||
TypeVisitor,
|
TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg};
|
use rustc_errors::{into_diag_arg_using_display, Applicability, Diag, DiagArgValue, IntoDiagArg};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -19,10 +19,9 @@ use rustc_hir::{PredicateOrigin, WherePredicate};
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
use rustc_type_ir::TyKind::*;
|
use rustc_type_ir::TyKind::*;
|
||||||
|
|
||||||
impl<'tcx> IntoDiagArg for Ty<'tcx> {
|
into_diag_arg_using_display! {
|
||||||
fn into_diag_arg(self) -> DiagArgValue {
|
Ty<'_>,
|
||||||
self.to_string().into_diag_arg()
|
ty::Region<'_>,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Ty<'tcx> {
|
impl<'tcx> Ty<'tcx> {
|
||||||
|
|
|
@ -154,6 +154,14 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||||
}) {
|
}) {
|
||||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||||
|
|
||||||
|
// This analysis only makes sense if the parent capture is a
|
||||||
|
// prefix of the child capture.
|
||||||
|
assert!(
|
||||||
|
child_capture.place.projections.len() >= parent_capture.place.projections.len(),
|
||||||
|
"parent capture ({parent_capture:#?}) expected to be prefix of \
|
||||||
|
child capture ({child_capture:#?})"
|
||||||
|
);
|
||||||
|
|
||||||
// Store this set of additional projections (fields and derefs).
|
// Store this set of additional projections (fields and derefs).
|
||||||
// We need to re-apply them later.
|
// We need to re-apply them later.
|
||||||
let child_precise_captures =
|
let child_precise_captures =
|
||||||
|
@ -244,7 +252,6 @@ fn child_prefix_matches_parent_projections(
|
||||||
bug!("expected capture to be an upvar");
|
bug!("expected capture to be an upvar");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(child_capture.place.projections.len() >= parent_capture.place.projections.len());
|
|
||||||
parent_base.var_path.hir_id == child_base.var_path.hir_id
|
parent_base.var_path.hir_id == child_base.var_path.hir_id
|
||||||
&& std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
|
&& std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
|
||||||
.all(|(child, parent)| child.kind == parent.kind)
|
.all(|(child, parent)| child.kind == parent.kind)
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
//! monomorphic body using internal representation.
|
//! monomorphic body using internal representation.
|
||||||
//! After that, we convert the internal representation into a stable one.
|
//! After that, we convert the internal representation into a stable one.
|
||||||
use crate::rustc_smir::{Stable, Tables};
|
use crate::rustc_smir::{Stable, Tables};
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::visit::MutVisitor;
|
use rustc_middle::mir::visit::MutVisitor;
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
|
||||||
/// Builds a monomorphic body for a given instance.
|
/// Builds a monomorphic body for a given instance.
|
||||||
pub struct BodyBuilder<'tcx> {
|
pub struct BodyBuilder<'tcx> {
|
||||||
|
@ -16,46 +17,43 @@ pub struct BodyBuilder<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> BodyBuilder<'tcx> {
|
impl<'tcx> BodyBuilder<'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
|
||||||
|
let instance = match instance.def {
|
||||||
|
// To get the fallback body of an intrinsic, we need to convert it to an item.
|
||||||
|
ty::InstanceDef::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
|
||||||
|
_ => instance,
|
||||||
|
};
|
||||||
BodyBuilder { tcx, instance }
|
BodyBuilder { tcx, instance }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a stable monomorphic body for a given instance based on the MIR body.
|
/// Build a stable monomorphic body for a given instance based on the MIR body.
|
||||||
///
|
///
|
||||||
/// Note that we skip instantiation for static and constants. Trying to do so can cause ICE.
|
/// All constants are also evaluated.
|
||||||
///
|
|
||||||
/// We do monomorphize non-generic functions to eval unevaluated constants.
|
|
||||||
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
|
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
|
||||||
let mut body = self.tcx.instance_mir(self.instance.def).clone();
|
let body = tables.tcx.instance_mir(self.instance.def).clone();
|
||||||
if self.tcx.def_kind(self.instance.def_id()).is_fn_like() || !self.instance.args.is_empty()
|
let mono_body = if !self.instance.args.is_empty()
|
||||||
|
// Without the `generic_const_exprs` feature gate, anon consts in signatures do not
|
||||||
|
// get generic parameters. Which is wrong, but also not a problem without
|
||||||
|
// generic_const_exprs
|
||||||
|
|| self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
|
||||||
{
|
{
|
||||||
self.visit_body(&mut body);
|
let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||||
}
|
tables.tcx,
|
||||||
body.stable(tables)
|
ty::ParamEnv::reveal_all(),
|
||||||
}
|
ty::EarlyBinder::bind(body),
|
||||||
|
);
|
||||||
fn monomorphize<T>(&self, value: T) -> T
|
self.visit_body(&mut mono_body);
|
||||||
where
|
mono_body
|
||||||
T: ty::TypeFoldable<TyCtxt<'tcx>>,
|
} else {
|
||||||
{
|
// Already monomorphic.
|
||||||
self.instance.instantiate_mir_and_normalize_erasing_regions(
|
body
|
||||||
self.tcx,
|
};
|
||||||
ty::ParamEnv::reveal_all(),
|
mono_body.stable(tables)
|
||||||
ty::EarlyBinder::bind(value),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
||||||
fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, _location: mir::Location) {
|
|
||||||
*ct = self.monomorphize(*ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: mir::visit::TyContext) {
|
|
||||||
*ty = self.monomorphize(*ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
|
fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
|
||||||
let const_ = self.monomorphize(constant.const_);
|
let const_ = constant.const_;
|
||||||
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
|
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
|
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
|
||||||
|
@ -68,10 +66,6 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
||||||
self.super_constant(constant, location);
|
self.super_constant(constant, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, _: mir::Location) {
|
|
||||||
*args = self.monomorphize(*args);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,10 +133,14 @@ fn layout_of_uncached<'tcx>(
|
||||||
ty::PatternKind::Range { start, end, include_end } => {
|
ty::PatternKind::Range { start, end, include_end } => {
|
||||||
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
|
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
|
||||||
if let Some(start) = start {
|
if let Some(start) = start {
|
||||||
scalar.valid_range_mut().start = start.eval_bits(tcx, param_env);
|
scalar.valid_range_mut().start = start
|
||||||
|
.try_eval_bits(tcx, param_env)
|
||||||
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
}
|
}
|
||||||
if let Some(end) = end {
|
if let Some(end) = end {
|
||||||
let mut end = end.eval_bits(tcx, param_env);
|
let mut end = end
|
||||||
|
.try_eval_bits(tcx, param_env)
|
||||||
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
if !include_end {
|
if !include_end {
|
||||||
end = end.wrapping_sub(1);
|
end = end.wrapping_sub(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,22 @@ impl Instance {
|
||||||
with(|cx| cx.instance_args(self.def))
|
with(|cx| cx.instance_args(self.def))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the body of an Instance. The body will be eagerly monomorphized.
|
/// Get the body of an Instance.
|
||||||
|
///
|
||||||
|
/// The body will be eagerly monomorphized and all constants will already be evaluated.
|
||||||
|
///
|
||||||
|
/// This method will return the intrinsic fallback body if one was defined.
|
||||||
pub fn body(&self) -> Option<Body> {
|
pub fn body(&self) -> Option<Body> {
|
||||||
with(|context| context.instance_body(self.def))
|
with(|context| context.instance_body(self.def))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether this instance has a body available.
|
/// Check whether this instance has a body available.
|
||||||
///
|
///
|
||||||
|
/// For intrinsics with fallback body, this will return `true`. It is up to the user to decide
|
||||||
|
/// whether to specialize the intrinsic or to use its fallback body.
|
||||||
|
///
|
||||||
|
/// For more information on fallback body, see <https://github.com/rust-lang/rust/issues/93145>.
|
||||||
|
///
|
||||||
/// This call is much cheaper than `instance.body().is_some()`, since it doesn't try to build
|
/// This call is much cheaper than `instance.body().is_some()`, since it doesn't try to build
|
||||||
/// the StableMIR body.
|
/// the StableMIR body.
|
||||||
pub fn has_body(&self) -> bool {
|
pub fn has_body(&self) -> bool {
|
||||||
|
|
|
@ -34,6 +34,102 @@ use core::ptr::addr_of;
|
||||||
|
|
||||||
use super::c;
|
use super::c;
|
||||||
|
|
||||||
|
/// Creates a null-terminated UTF-16 string from a str.
|
||||||
|
pub macro wide_str($str:literal) {{
|
||||||
|
const _: () = {
|
||||||
|
if core::slice::memchr::memchr(0, $str.as_bytes()).is_some() {
|
||||||
|
panic!("null terminated strings cannot contain interior nulls");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
crate::sys::pal::windows::api::utf16!(concat!($str, '\0'))
|
||||||
|
}}
|
||||||
|
|
||||||
|
/// Creates a UTF-16 string from a str without null termination.
|
||||||
|
pub macro utf16($str:expr) {{
|
||||||
|
const UTF8: &str = $str;
|
||||||
|
const UTF16_LEN: usize = crate::sys::pal::windows::api::utf16_len(UTF8);
|
||||||
|
const UTF16: [u16; UTF16_LEN] = crate::sys::pal::windows::api::to_utf16(UTF8);
|
||||||
|
&UTF16
|
||||||
|
}}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
/// Gets the UTF-16 length of a UTF-8 string, for use in the wide_str macro.
|
||||||
|
pub const fn utf16_len(s: &str) -> usize {
|
||||||
|
let s = s.as_bytes();
|
||||||
|
let mut i = 0;
|
||||||
|
let mut len = 0;
|
||||||
|
while i < s.len() {
|
||||||
|
// the length of a UTF-8 encoded code-point is given by the number of
|
||||||
|
// leading ones, except in the case of ASCII.
|
||||||
|
let utf8_len = match s[i].leading_ones() {
|
||||||
|
0 => 1,
|
||||||
|
n => n as usize,
|
||||||
|
};
|
||||||
|
i += utf8_len;
|
||||||
|
// Note that UTF-16 surrogates (U+D800 to U+DFFF) are not encodable as UTF-8,
|
||||||
|
// so (unlike with WTF-8) we don't have to worry about how they'll get re-encoded.
|
||||||
|
len += if utf8_len < 4 { 1 } else { 2 };
|
||||||
|
}
|
||||||
|
len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Const convert UTF-8 to UTF-16, for use in the wide_str macro.
|
||||||
|
///
|
||||||
|
/// Note that this is designed for use in const contexts so is not optimized.
|
||||||
|
pub const fn to_utf16<const UTF16_LEN: usize>(s: &str) -> [u16; UTF16_LEN] {
|
||||||
|
let mut output = [0_u16; UTF16_LEN];
|
||||||
|
let mut pos = 0;
|
||||||
|
let s = s.as_bytes();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < s.len() {
|
||||||
|
match s[i].leading_ones() {
|
||||||
|
// Decode UTF-8 based on its length.
|
||||||
|
// See https://en.wikipedia.org/wiki/UTF-8
|
||||||
|
0 => {
|
||||||
|
// ASCII is the same in both encodings
|
||||||
|
output[pos] = s[i] as u16;
|
||||||
|
i += 1;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
// Bits: 110xxxxx 10xxxxxx
|
||||||
|
output[pos] = ((s[i] as u16 & 0b11111) << 6) | (s[i + 1] as u16 & 0b111111);
|
||||||
|
i += 2;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
// Bits: 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
output[pos] = ((s[i] as u16 & 0b1111) << 12)
|
||||||
|
| ((s[i + 1] as u16 & 0b111111) << 6)
|
||||||
|
| (s[i + 2] as u16 & 0b111111);
|
||||||
|
i += 3;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
// Bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
let mut c = ((s[i] as u32 & 0b111) << 18)
|
||||||
|
| ((s[i + 1] as u32 & 0b111111) << 12)
|
||||||
|
| ((s[i + 2] as u32 & 0b111111) << 6)
|
||||||
|
| (s[i + 3] as u32 & 0b111111);
|
||||||
|
// re-encode as UTF-16 (see https://en.wikipedia.org/wiki/UTF-16)
|
||||||
|
// - Subtract 0x10000 from the code point
|
||||||
|
// - For the high surrogate, shift right by 10 then add 0xD800
|
||||||
|
// - For the low surrogate, take the low 10 bits then add 0xDC00
|
||||||
|
c -= 0x10000;
|
||||||
|
output[pos] = ((c >> 10) + 0xD800) as u16;
|
||||||
|
output[pos + 1] = ((c & 0b1111111111) + 0xDC00) as u16;
|
||||||
|
i += 4;
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
// valid UTF-8 cannot have any other values
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper method for getting the size of `T` as a u32.
|
/// Helper method for getting the size of `T` as a u32.
|
||||||
/// Errors at compile time if the size would overflow.
|
/// Errors at compile time if the size would overflow.
|
||||||
///
|
///
|
||||||
|
|
16
library/std/src/sys/pal/windows/api/tests.rs
Normal file
16
library/std/src/sys/pal/windows/api/tests.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use crate::sys::pal::windows::api::{utf16, wide_str};
|
||||||
|
|
||||||
|
macro_rules! check_utf16 {
|
||||||
|
($str:literal) => {{
|
||||||
|
assert!(wide_str!($str).iter().copied().eq($str.encode_utf16().chain([0])));
|
||||||
|
assert!(utf16!($str).iter().copied().eq($str.encode_utf16()));
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_utf16_macros() {
|
||||||
|
check_utf16!("hello world");
|
||||||
|
check_utf16!("€4.50");
|
||||||
|
check_utf16!("𨉟呐㗂越");
|
||||||
|
check_utf16!("Pchnąć w tę łódź jeża lub ośm skrzyń fig");
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ use crate::io::ErrorKind;
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
|
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
use crate::path::PathBuf;
|
use crate::path::PathBuf;
|
||||||
|
use crate::sys::pal::windows::api::wide_str;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub use self::rand::hashmap_random_keys;
|
pub use self::rand::hashmap_random_keys;
|
||||||
|
@ -12,6 +13,8 @@ pub use self::rand::hashmap_random_keys;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod compat;
|
pub mod compat;
|
||||||
|
|
||||||
|
mod api;
|
||||||
|
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod c;
|
pub mod c;
|
||||||
|
@ -41,8 +44,6 @@ cfg_if::cfg_if! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod api;
|
|
||||||
|
|
||||||
/// Map a Result<T, WinError> to io::Result<T>.
|
/// Map a Result<T, WinError> to io::Result<T>.
|
||||||
trait IoResult<T> {
|
trait IoResult<T> {
|
||||||
fn io_result(self) -> crate::io::Result<T>;
|
fn io_result(self) -> crate::io::Result<T>;
|
||||||
|
@ -60,7 +61,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
|
||||||
|
|
||||||
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
|
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
|
||||||
// exists, we have to call it ourselves.
|
// exists, we have to call it ourselves.
|
||||||
thread::Thread::set_name(&c"main");
|
thread::Thread::set_name_wide(wide_str!("main"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: must be called only once during runtime cleanup.
|
// SAFETY: must be called only once during runtime cleanup.
|
||||||
|
|
|
@ -59,13 +59,17 @@ impl Thread {
|
||||||
pub fn set_name(name: &CStr) {
|
pub fn set_name(name: &CStr) {
|
||||||
if let Ok(utf8) = name.to_str() {
|
if let Ok(utf8) = name.to_str() {
|
||||||
if let Ok(utf16) = to_u16s(utf8) {
|
if let Ok(utf16) = to_u16s(utf8) {
|
||||||
unsafe {
|
Self::set_name_wide(&utf16)
|
||||||
c::SetThreadDescription(c::GetCurrentThread(), utf16.as_ptr());
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_name_wide(name: &[u16]) {
|
||||||
|
unsafe {
|
||||||
|
c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn join(self) {
|
pub fn join(self) {
|
||||||
let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
|
let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
|
||||||
if rc == c::WAIT_FAILED {
|
if rc == c::WAIT_FAILED {
|
||||||
|
|
|
@ -231,7 +231,7 @@ impl<'tcx> Context<'tcx> {
|
||||||
rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
|
rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
|
||||||
};
|
};
|
||||||
let mut page_buffer = Buffer::html();
|
let mut page_buffer = Buffer::html();
|
||||||
print_item(self, it, &mut page_buffer, &page);
|
print_item(self, it, &mut page_buffer);
|
||||||
layout::render(
|
layout::render(
|
||||||
&clone_shared.layout,
|
&clone_shared.layout,
|
||||||
&page,
|
&page,
|
||||||
|
|
|
@ -31,11 +31,10 @@ use crate::html::format::{
|
||||||
display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space,
|
display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space,
|
||||||
print_where_clause, visibility_print_with_space, Buffer, Ending, PrintWithSpace,
|
print_where_clause, visibility_print_with_space, Buffer, Ending, PrintWithSpace,
|
||||||
};
|
};
|
||||||
use crate::html::layout::Page;
|
use crate::html::highlight;
|
||||||
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
||||||
use crate::html::render::{document_full, document_item_info};
|
use crate::html::render::{document_full, document_item_info};
|
||||||
use crate::html::url_parts_builder::UrlPartsBuilder;
|
use crate::html::url_parts_builder::UrlPartsBuilder;
|
||||||
use crate::html::{highlight, static_files};
|
|
||||||
|
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -157,8 +156,6 @@ struct PathComponent {
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "print_item.html")]
|
#[template(path = "print_item.html")]
|
||||||
struct ItemVars<'a> {
|
struct ItemVars<'a> {
|
||||||
static_root_path: &'a str,
|
|
||||||
clipboard_svg: &'static static_files::StaticFile,
|
|
||||||
typ: &'a str,
|
typ: &'a str,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
item_type: &'a str,
|
item_type: &'a str,
|
||||||
|
@ -178,12 +175,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
|
||||||
len_before != buffer.len()
|
len_before != buffer.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn print_item(
|
pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
|
||||||
cx: &mut Context<'_>,
|
|
||||||
item: &clean::Item,
|
|
||||||
buf: &mut Buffer,
|
|
||||||
page: &Page<'_>,
|
|
||||||
) {
|
|
||||||
debug_assert!(!item.is_stripped());
|
debug_assert!(!item.is_stripped());
|
||||||
let typ = match *item.kind {
|
let typ = match *item.kind {
|
||||||
clean::ModuleItem(_) => {
|
clean::ModuleItem(_) => {
|
||||||
|
@ -252,8 +244,6 @@ pub(super) fn print_item(
|
||||||
};
|
};
|
||||||
|
|
||||||
let item_vars = ItemVars {
|
let item_vars = ItemVars {
|
||||||
static_root_path: &page.get_static_root_path(),
|
|
||||||
clipboard_svg: &static_files::STATIC_FILES.clipboard_svg,
|
|
||||||
typ,
|
typ,
|
||||||
name: item.name.as_ref().unwrap().as_str(),
|
name: item.name.as_ref().unwrap().as_str(),
|
||||||
item_type: &item.type_().to_string(),
|
item_type: &item.type_().to_string(),
|
||||||
|
@ -1237,22 +1227,18 @@ fn item_opaque_ty(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
|
fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
|
||||||
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
|
wrap_item(w, |w| {
|
||||||
wrap_item(w, |w| {
|
write!(
|
||||||
write!(
|
w,
|
||||||
w,
|
"{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
|
||||||
"{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
|
attrs = render_attributes_in_pre(it, "", cx),
|
||||||
attrs = render_attributes_in_pre(it, "", cx),
|
vis = visibility_print_with_space(it, cx),
|
||||||
vis = visibility_print_with_space(it, cx),
|
name = it.name.unwrap(),
|
||||||
name = it.name.unwrap(),
|
generics = t.generics.print(cx),
|
||||||
generics = t.generics.print(cx),
|
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
|
||||||
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
|
type_ = t.type_.print(cx),
|
||||||
type_ = t.type_.print(cx),
|
);
|
||||||
);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
write_content(w, cx, it, t);
|
|
||||||
|
|
||||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
||||||
|
|
||||||
|
|
|
@ -1603,6 +1603,16 @@ a.tooltip:hover::after {
|
||||||
border-color: var(--settings-button-border-focus);
|
border-color: var(--settings-button-border-focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#settings-menu > a {
|
||||||
|
line-height: 0;
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
#settings-menu > a:before {
|
||||||
|
content: url('wheel-63255fc4502dca9a.svg');
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
#sidebar-button > a:before {
|
#sidebar-button > a:before {
|
||||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" \
|
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" \
|
||||||
fill="none" stroke="black">\
|
fill="none" stroke="black">\
|
||||||
|
@ -1622,11 +1632,17 @@ a.tooltip:hover::after {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
border: 0;
|
border: 0;
|
||||||
width: 33px;
|
width: 33px;
|
||||||
|
line-height: 0;
|
||||||
|
font-size: 0;
|
||||||
}
|
}
|
||||||
#copy-path > img {
|
|
||||||
|
#copy-path:before {
|
||||||
filter: var(--copy-path-img-filter);
|
filter: var(--copy-path-img-filter);
|
||||||
|
content: url('clipboard-24048e6d87f63d07.svg');
|
||||||
|
width: 19px;
|
||||||
|
height: 18px;
|
||||||
}
|
}
|
||||||
#copy-path:hover > img {
|
#copy-path:hover:before {
|
||||||
filter: var(--copy-path-img-hover-filter);
|
filter: var(--copy-path-img-hover-filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<svg width="24" height="25" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
|
<svg width="19" height="18" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
|
||||||
|
|
Before Width: | Height: | Size: 576 B After Width: | Height: | Size: 576 B |
Binary file not shown.
Before Width: | Height: | Size: 715 B |
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" viewBox="0 0 27.434 29.5"><path d="M27.316 18.39a2.696 2.696 0 0 0-.98-1.46 1.62 1.62 0 0 1-.016-.762l.035-.176v-1.191c0-1.246-.003-1.278-.046-1.473a1.717 1.717 0 0 1 .007-.805c.477-.343.829-.859.997-1.472.257-.957.074-2.094-.508-3.117l-.594-1.032c-.746-1.304-1.965-2.117-3.18-2.117-.379 0-.75.078-1.086.235a1.958 1.958 0 0 1-.855-.391l-.102-.082-.117-.063-1.855-1.07-.094-.055-.106-.043c-.378-.156-.66-.41-.77-.554C17.919 1.172 16.349 0 14.297 0h-1.155c-2.043 0-3.61 1.152-3.75 2.723-.114.14-.391.382-.758.527l-.102.04-.094.05-1.94 1.066-.134.074-.117.094a2.019 2.019 0 0 1-.832.403 2.518 2.518 0 0 0-1.008-.211c-1.199 0-2.414.82-3.168 2.14l-.59 1.032c-.41.718-.64 1.523-.64 2.257-.004.953.36 1.758 1.012 2.258.035.152.058.445-.016.785-.04.168-.063.282-.063 1.563 0 1.148 0 1.148.016 1.261l.008.075.015.074c.075.344.047.64.012.8-.644.5-1.004 1.302-.992 2.259.008.726.238 1.52.648 2.242l.59 1.027c.758 1.332 1.965 2.16 3.149 2.16.324 0 .644-.062.937-.187.168.039.492.156.813.418l.11.086.124.07 2.047 1.156.102.059.105.043c.363.144.648.379.766.52.164 1.519 1.718 2.632 3.746 2.632h1.156c2.035 0 3.598-1.133 3.746-2.672.117-.144.402-.394.773-.55l.114-.047.101-.063 1.961-1.156.106-.063.097-.078c.309-.246.653-.37.832-.398.313.136.66.21 1.016.21 1.2 0 2.41-.82 3.164-2.14l.594-1.031c.59-1.028.777-2.164.52-3.117Zm-2.043 2.247-.59 1.031c-.437.766-1.105 1.25-1.636 1.25a.7.7 0 0 1-.371-.094 1.146 1.146 0 0 0-.567-.129c-.593 0-1.382.297-2.007.797l-1.961 1.156c-1.016.426-1.848 1.293-1.848 1.93 0 .64-.898 1.16-1.996 1.16H13.14c-1.102 0-2-.515-2-1.14 0-.63-.832-1.477-1.852-1.887l-2.047-1.16c-.637-.512-1.426-.813-2.008-.813-.199 0-.379.035-.515.114a.648.648 0 0 1-.332.085c-.52 0-1.18-.5-1.621-1.273l-.59-1.031c-.543-.953-.555-1.98-.024-2.285.532-.305.782-1.434.551-2.504V14.8c0-1.09.02-1.18.02-1.18.238-1.074-.008-2.203-.551-2.516-.54-.304-.54-1.34.008-2.293l.59-1.03c.437-.766 1.101-1.255 1.636-1.255a.73.73 0 0 1 .364.094c.152.086.343.125.566.125.594 0 1.379-.297 2.004-.793l1.945-1.066c1.02-.407 1.856-1.278 1.856-1.934 0-.656.898-1.191 2-1.191h1.156c1.098 0 1.996.543 1.996 1.21 0 .669.832 1.555 1.848 1.973L20 6.012c.617.492 1.402.777 2.012.777.242 0 .453-.047.62-.14a.79.79 0 0 1 .403-.102c.55 0 1.223.476 1.652 1.23l.59 1.032c.543.953.52 2.004-.062 2.336-.574.332-.86 1.48-.625 2.554 0 0 .008.04.008 1.102v1.011c-.215 1.051.07 2.176.636 2.5.567.325.586 1.368.04 2.325Zm0 0"/><path d="M13.61 7.61a7.084 7.084 0 0 0-7.083 7.085 7.085 7.085 0 1 0 14.168 0A7.088 7.088 0 0 0 13.61 7.61Zm0 12.41a5.33 5.33 0 0 1-5.325-5.325 5.33 5.33 0 0 1 5.324-5.32 5.327 5.327 0 0 1 5.325 5.32 5.328 5.328 0 0 1-5.325 5.325Zm0 0"/><path d="M13.684 9.906a4.722 4.722 0 0 0-4.72 4.719 4.722 4.722 0 0 0 4.72 4.719 4.724 4.724 0 0 0 4.714-4.719 4.724 4.724 0 0 0-4.714-4.719Zm0 7.676a2.954 2.954 0 1 1 0-5.91 2.953 2.953 0 0 1 2.953 2.953 2.957 2.957 0 0 1-2.953 2.957Zm0 0"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" enable-background="new 0 0 22 22" viewBox="0 0 27.434 29.5"><path d="M27.316 18.39a2.696 2.696 0 0 0-.98-1.46 1.62 1.62 0 0 1-.016-.762l.035-.176v-1.191c0-1.246-.003-1.278-.046-1.473a1.717 1.717 0 0 1 .007-.805c.477-.343.829-.859.997-1.472.257-.957.074-2.094-.508-3.117l-.594-1.032c-.746-1.304-1.965-2.117-3.18-2.117-.379 0-.75.078-1.086.235a1.958 1.958 0 0 1-.855-.391l-.102-.082-.117-.063-1.855-1.07-.094-.055-.106-.043c-.378-.156-.66-.41-.77-.554C17.919 1.172 16.349 0 14.297 0h-1.155c-2.043 0-3.61 1.152-3.75 2.723-.114.14-.391.382-.758.527l-.102.04-.094.05-1.94 1.066-.134.074-.117.094a2.019 2.019 0 0 1-.832.403 2.518 2.518 0 0 0-1.008-.211c-1.199 0-2.414.82-3.168 2.14l-.59 1.032c-.41.718-.64 1.523-.64 2.257-.004.953.36 1.758 1.012 2.258.035.152.058.445-.016.785-.04.168-.063.282-.063 1.563 0 1.148 0 1.148.016 1.261l.008.075.015.074c.075.344.047.64.012.8-.644.5-1.004 1.302-.992 2.259.008.726.238 1.52.648 2.242l.59 1.027c.758 1.332 1.965 2.16 3.149 2.16.324 0 .644-.062.937-.187.168.039.492.156.813.418l.11.086.124.07 2.047 1.156.102.059.105.043c.363.144.648.379.766.52.164 1.519 1.718 2.632 3.746 2.632h1.156c2.035 0 3.598-1.133 3.746-2.672.117-.144.402-.394.773-.55l.114-.047.101-.063 1.961-1.156.106-.063.097-.078c.309-.246.653-.37.832-.398.313.136.66.21 1.016.21 1.2 0 2.41-.82 3.164-2.14l.594-1.031c.59-1.028.777-2.164.52-3.117Zm-2.043 2.247-.59 1.031c-.437.766-1.105 1.25-1.636 1.25a.7.7 0 0 1-.371-.094 1.146 1.146 0 0 0-.567-.129c-.593 0-1.382.297-2.007.797l-1.961 1.156c-1.016.426-1.848 1.293-1.848 1.93 0 .64-.898 1.16-1.996 1.16H13.14c-1.102 0-2-.515-2-1.14 0-.63-.832-1.477-1.852-1.887l-2.047-1.16c-.637-.512-1.426-.813-2.008-.813-.199 0-.379.035-.515.114a.648.648 0 0 1-.332.085c-.52 0-1.18-.5-1.621-1.273l-.59-1.031c-.543-.953-.555-1.98-.024-2.285.532-.305.782-1.434.551-2.504V14.8c0-1.09.02-1.18.02-1.18.238-1.074-.008-2.203-.551-2.516-.54-.304-.54-1.34.008-2.293l.59-1.03c.437-.766 1.101-1.255 1.636-1.255a.73.73 0 0 1 .364.094c.152.086.343.125.566.125.594 0 1.379-.297 2.004-.793l1.945-1.066c1.02-.407 1.856-1.278 1.856-1.934 0-.656.898-1.191 2-1.191h1.156c1.098 0 1.996.543 1.996 1.21 0 .669.832 1.555 1.848 1.973L20 6.012c.617.492 1.402.777 2.012.777.242 0 .453-.047.62-.14a.79.79 0 0 1 .403-.102c.55 0 1.223.476 1.652 1.23l.59 1.032c.543.953.52 2.004-.062 2.336-.574.332-.86 1.48-.625 2.554 0 0 .008.04.008 1.102v1.011c-.215 1.051.07 2.176.636 2.5.567.325.586 1.368.04 2.325Zm0 0"/><path d="M13.61 7.61a7.084 7.084 0 0 0-7.083 7.085 7.085 7.085 0 1 0 14.168 0A7.088 7.088 0 0 0 13.61 7.61Zm0 12.41a5.33 5.33 0 0 1-5.325-5.325 5.33 5.33 0 0 1 5.324-5.32 5.327 5.327 0 0 1 5.325 5.32 5.328 5.328 0 0 1-5.325 5.325Zm0 0"/><path d="M13.684 9.906a4.722 4.722 0 0 0-4.72 4.719 4.722 4.722 0 0 0 4.72 4.719 4.724 4.724 0 0 0 4.714-4.719 4.724 4.724 0 0 0-4.714-4.719Zm0 7.676a2.954 2.954 0 1 1 0-5.91 2.953 2.953 0 0 1 2.953 2.953 2.957 2.957 0 0 1-2.953 2.957Zm0 0"/></svg>
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
@ -106,7 +106,6 @@ static_files! {
|
||||||
license_mit => "static/LICENSE-MIT.txt",
|
license_mit => "static/LICENSE-MIT.txt",
|
||||||
rust_logo_svg => "static/images/rust-logo.svg",
|
rust_logo_svg => "static/images/rust-logo.svg",
|
||||||
rust_favicon_svg => "static/images/favicon.svg",
|
rust_favicon_svg => "static/images/favicon.svg",
|
||||||
rust_favicon_png_16 => "static/images/favicon-16x16.png",
|
|
||||||
rust_favicon_png_32 => "static/images/favicon-32x32.png",
|
rust_favicon_png_32 => "static/images/favicon-32x32.png",
|
||||||
fira_sans_regular => "static/fonts/FiraSans-Regular.woff2",
|
fira_sans_regular => "static/fonts/FiraSans-Regular.woff2",
|
||||||
fira_sans_medium => "static/fonts/FiraSans-Medium.woff2",
|
fira_sans_medium => "static/fonts/FiraSans-Medium.woff2",
|
||||||
|
|
|
@ -6,13 +6,10 @@
|
||||||
<meta name="generator" content="rustdoc"> {# #}
|
<meta name="generator" content="rustdoc"> {# #}
|
||||||
<meta name="description" content="{{page.description}}"> {# #}
|
<meta name="description" content="{{page.description}}"> {# #}
|
||||||
<title>{{page.title}}</title> {# #}
|
<title>{{page.title}}</title> {# #}
|
||||||
<script> if (window.location.protocol !== "file:") document.write(` {# Hack to skip preloading fonts locally - see #98769 #}
|
<script>if(window.location.protocol!=="file:") {# Hack to skip preloading fonts locally - see #98769 #}
|
||||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {# #}
|
for(f of "{{files.source_serif_4_regular}},{{files.fira_sans_regular}},{{files.fira_sans_medium}},{{files.source_code_pro_regular}},{{files.source_code_pro_semibold}}".split(",")) {# #}
|
||||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {# #}
|
document.write(`<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}${f}">`) {# #}
|
||||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {# #}
|
</script> {# #}
|
||||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {# #}
|
|
||||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {# #}
|
|
||||||
`)</script> {# #}
|
|
||||||
<link rel="stylesheet" {#+ #}
|
<link rel="stylesheet" {#+ #}
|
||||||
href="{{static_root_path|safe}}{{files.normalize_css}}"> {# #}
|
href="{{static_root_path|safe}}{{files.normalize_css}}"> {# #}
|
||||||
<link rel="stylesheet" {#+ #}
|
<link rel="stylesheet" {#+ #}
|
||||||
|
@ -61,8 +58,6 @@
|
||||||
{% if !layout.favicon.is_empty() %}
|
{% if !layout.favicon.is_empty() %}
|
||||||
<link rel="icon" href="{{layout.favicon}}"> {# #}
|
<link rel="icon" href="{{layout.favicon}}"> {# #}
|
||||||
{% else %}
|
{% else %}
|
||||||
<link rel="alternate icon" type="image/png" {#+ #}
|
|
||||||
href="{{static_root_path|safe}}{{files.rust_favicon_png_16}}"> {# #}
|
|
||||||
<link rel="alternate icon" type="image/png" {#+ #}
|
<link rel="alternate icon" type="image/png" {#+ #}
|
||||||
href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {# #}
|
href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {# #}
|
||||||
<link rel="icon" type="image/svg+xml" {#+ #}
|
<link rel="icon" type="image/svg+xml" {#+ #}
|
||||||
|
@ -114,13 +109,13 @@
|
||||||
<div class="version">{{+ display_krate_version_extra}}</div> {# #}
|
<div class="version">{{+ display_krate_version_extra}}</div> {# #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="src-sidebar-title">
|
<div class="src-sidebar-title"> {# #}
|
||||||
<h2>Files</h2> {# #}
|
<h2>Files</h2> {# #}
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ sidebar|safe }}
|
{{ sidebar|safe }}
|
||||||
</nav> {# #}
|
</nav> {# #}
|
||||||
<div class="sidebar-resizer"></div>
|
<div class="sidebar-resizer"></div> {# #}
|
||||||
<main> {# #}
|
<main> {# #}
|
||||||
{% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
|
{% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
|
||||||
<nav class="sub"> {# #}
|
<nav class="sub"> {# #}
|
||||||
|
@ -142,8 +137,7 @@
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
<div id="settings-menu" tabindex="-1"> {# #}
|
<div id="settings-menu" tabindex="-1"> {# #}
|
||||||
<a href="{{page.root_path|safe}}settings.html" title="settings"> {# #}
|
<a href="{{page.root_path|safe}}settings.html" title="settings"> {# #}
|
||||||
<img width="22" height="22" alt="Change settings" {#+ #}
|
Settings {# #}
|
||||||
src="{{static_root_path|safe}}{{files.wheel_svg}}"> {# #}
|
|
||||||
</a> {# #}
|
</a> {# #}
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
</form> {# #}
|
</form> {# #}
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<a class="{{item_type}}" href="#">{{name}}</a> {# #}
|
<a class="{{item_type}}" href="#">{{name}}</a> {# #}
|
||||||
<button id="copy-path" title="Copy item path to clipboard"> {# #}
|
<button id="copy-path" title="Copy item path to clipboard"> {# #}
|
||||||
<img src="{{static_root_path|safe}}{{clipboard_svg}}" {#+ #}
|
Copy item path {# #}
|
||||||
width="19" height="18" {#+ #}
|
|
||||||
alt="Copy item path"> {# #}
|
|
||||||
</button> {# #}
|
</button> {# #}
|
||||||
</h1> {# #}
|
</h1> {# #}
|
||||||
<span class="out-of-band">
|
<span class="out-of-band">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="sidebar-elems">
|
<div class="sidebar-elems">
|
||||||
{% if is_crate %}
|
{% if is_crate %}
|
||||||
<ul class="block">
|
<ul class="block"> {# #}
|
||||||
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
|
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
// First, we check that the first page doesn't have the string we're looking for to ensure
|
// First, we check that the first page doesn't have the string we're looking for to ensure
|
||||||
// that the feature is changing page as expected.
|
// that the feature is changing page as expected.
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||||
assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
|
assert-text-false: (".main-heading h1", "Struct test_docs::FooCopy item path")
|
||||||
|
|
||||||
// We now check that we land on the search result page if "go_to_first" isn't set.
|
// We now check that we land on the search result page if "go_to_first" isn't set.
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
|
||||||
// Waiting for the search results to appear...
|
// Waiting for the search results to appear...
|
||||||
wait-for: "#search-tabs"
|
wait-for: "#search-tabs"
|
||||||
assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
|
assert-text-false: (".main-heading h1", "Struct test_docs::FooCopy item path")
|
||||||
// Ensure that the search results are displayed, not the "normal" content.
|
// Ensure that the search results are displayed, not the "normal" content.
|
||||||
assert-css: ("#main-content", {"display": "none"})
|
assert-css: ("#main-content", {"display": "none"})
|
||||||
|
|
||||||
// Now we can check that the feature is working as expected!
|
// Now we can check that the feature is working as expected!
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
|
||||||
// Waiting for the page to load...
|
// Waiting for the page to load...
|
||||||
wait-for-text: (".main-heading h1", "Struct test_docs::Foo")
|
wait-for-text: (".main-heading h1", "Struct test_docs::FooCopy item path")
|
||||||
|
|
|
@ -12,4 +12,4 @@ assert-attribute-false: (".impl-items .toggle", {"open": ""})
|
||||||
|
|
||||||
// Click the "Trait" part of "impl Trait" and verify it navigates.
|
// Click the "Trait" part of "impl Trait" and verify it navigates.
|
||||||
click: "#impl-Trait-for-Foo h3 a:first-of-type"
|
click: "#impl-Trait-for-Foo h3 a:first-of-type"
|
||||||
assert-text: (".main-heading h1", "Trait lib2::Trait")
|
assert-text: (".main-heading h1", "Trait lib2::TraitCopy item path")
|
||||||
|
|
115
tests/ui-fulldeps/stable-mir/check_intrinsics.rs
Normal file
115
tests/ui-fulldeps/stable-mir/check_intrinsics.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
//@ run-pass
|
||||||
|
//! Test information regarding intrinsics and ensure we can retrieve the fallback body if it exists.
|
||||||
|
//!
|
||||||
|
//! This tests relies on the intrinsics implementation, and requires one intrinsic with and one
|
||||||
|
//! without a body. It doesn't matter which intrinsic is called here, and feel free to update that
|
||||||
|
//! if needed.
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
|
||||||
|
extern crate rustc_hir;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rustc_smir;
|
||||||
|
extern crate rustc_driver;
|
||||||
|
extern crate rustc_interface;
|
||||||
|
extern crate stable_mir;
|
||||||
|
|
||||||
|
use rustc_smir::rustc_internal;
|
||||||
|
use stable_mir::mir::mono::{Instance, InstanceKind};
|
||||||
|
use stable_mir::mir::visit::{Location, MirVisitor};
|
||||||
|
use stable_mir::mir::{LocalDecl, Terminator, TerminatorKind};
|
||||||
|
use stable_mir::ty::{RigidTy, TyKind};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
/// This function tests that we can correctly get type information from binary operations.
|
||||||
|
fn test_intrinsics() -> ControlFlow<()> {
|
||||||
|
// Find items in the local crate.
|
||||||
|
let main_def = stable_mir::all_local_items()[0];
|
||||||
|
let main_instance = Instance::try_from(main_def).unwrap();
|
||||||
|
let main_body = main_instance.body().unwrap();
|
||||||
|
let mut visitor = CallsVisitor { locals: main_body.locals(), calls: Default::default() };
|
||||||
|
visitor.visit_body(&main_body);
|
||||||
|
|
||||||
|
let calls = visitor.calls;
|
||||||
|
assert_eq!(calls.len(), 2, "Expected 2 calls, but found: {calls:?}");
|
||||||
|
for intrinsic in &calls {
|
||||||
|
check_intrinsic(intrinsic)
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This check is unfortunately tight to the implementation of intrinsics.
|
||||||
|
///
|
||||||
|
/// We want to ensure that StableMIR can handle intrinsics with and without fallback body.
|
||||||
|
///
|
||||||
|
/// If by any chance this test breaks because you changed how an intrinsic is implemented, please
|
||||||
|
/// update the test to invoke a different intrinsic.
|
||||||
|
fn check_intrinsic(intrinsic: &Instance) {
|
||||||
|
assert_eq!(intrinsic.kind, InstanceKind::Intrinsic);
|
||||||
|
let name = intrinsic.intrinsic_name().unwrap();
|
||||||
|
if intrinsic.has_body() {
|
||||||
|
let Some(body) = intrinsic.body() else { unreachable!("Expected a body") };
|
||||||
|
assert!(!body.blocks.is_empty());
|
||||||
|
assert_eq!(&name, "likely");
|
||||||
|
} else {
|
||||||
|
assert!(intrinsic.body().is_none());
|
||||||
|
assert_eq!(&name, "size_of_val");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CallsVisitor<'a> {
|
||||||
|
locals: &'a [LocalDecl],
|
||||||
|
calls: HashSet<Instance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MirVisitor for CallsVisitor<'a> {
|
||||||
|
fn visit_terminator(&mut self, term: &Terminator, _loc: Location) {
|
||||||
|
match &term.kind {
|
||||||
|
TerminatorKind::Call { func, .. } => {
|
||||||
|
let TyKind::RigidTy(RigidTy::FnDef(def, args)) =
|
||||||
|
func.ty(self.locals).unwrap().kind()
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.calls.insert(Instance::resolve(def, &args).unwrap());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||||
|
/// For that, it will first write the dummy crate into a file.
|
||||||
|
/// Then it will create a `StableMir` using custom arguments and then
|
||||||
|
/// it will run the compiler.
|
||||||
|
fn main() {
|
||||||
|
let path = "binop_input.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
|
||||||
|
run!(args, test_intrinsics).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
use std::intrinsics::*;
|
||||||
|
pub fn use_intrinsics(init: bool) -> bool {{
|
||||||
|
let sz = unsafe {{ size_of_val("hi") }};
|
||||||
|
likely(init && sz == 2)
|
||||||
|
}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
//@ check-pass
|
||||||
|
//@ edition: 2021
|
||||||
|
// issue: rust-lang/rust#123697
|
||||||
|
|
||||||
|
#![feature(async_closure)]
|
||||||
|
|
||||||
|
struct S { t: i32 }
|
||||||
|
|
||||||
|
fn test(s: &S, t: &i32) {
|
||||||
|
async || {
|
||||||
|
println!("{}", s.t);
|
||||||
|
println!("{}", t);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -1,36 +1,36 @@
|
||||||
//@ compile-flags:--cfg yes
|
//@ compile-flags:--cfg yes
|
||||||
|
|
||||||
fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(no)] T>() {}
|
fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(FALSE)] T>() {}
|
||||||
fn f_ty<#[cfg(no)] 'a: 'a, #[cfg(yes)] T>() {}
|
fn f_ty<#[cfg(FALSE)] 'a: 'a, #[cfg(yes)] T>() {}
|
||||||
|
|
||||||
type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK
|
type FnGood = for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> fn(); // OK
|
||||||
type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
|
type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn();
|
||||||
//~^ ERROR only lifetime parameters can be used in this context
|
//~^ ERROR only lifetime parameters can be used in this context
|
||||||
|
|
||||||
type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy; // OK
|
type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> Copy; // OK
|
||||||
type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
|
type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy;
|
||||||
//~^ ERROR only lifetime parameters can be used in this context
|
//~^ ERROR only lifetime parameters can be used in this context
|
||||||
|
|
||||||
struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(no)] T> u8: Copy; // OK
|
struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> u8: Copy; // OK
|
||||||
struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
|
struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy;
|
||||||
//~^ ERROR only lifetime parameters can be used in this context
|
//~^ ERROR only lifetime parameters can be used in this context
|
||||||
|
|
||||||
fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
|
fn f_lt_no<#[cfg_attr(FALSE, unknown)] 'a>() {} // OK
|
||||||
fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
|
fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
|
||||||
//~^ ERROR cannot find attribute `unknown` in this scope
|
//~^ ERROR cannot find attribute `unknown` in this scope
|
||||||
fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
|
fn f_ty_no<#[cfg_attr(FALSE, unknown)] T>() {} // OK
|
||||||
fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
|
fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
|
||||||
//~^ ERROR cannot find attribute `unknown` in this scope
|
//~^ ERROR cannot find attribute `unknown` in this scope
|
||||||
|
|
||||||
type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
|
type FnNo = for<#[cfg_attr(FALSE, unknown)] 'a> fn(); // OK
|
||||||
type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
|
type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
|
||||||
//~^ ERROR cannot find attribute `unknown` in this scope
|
//~^ ERROR cannot find attribute `unknown` in this scope
|
||||||
|
|
||||||
type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
|
type PolyNo = dyn for<#[cfg_attr(FALSE, unknown)] 'a> Copy; // OK
|
||||||
type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
|
type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
|
||||||
//~^ ERROR cannot find attribute `unknown` in this scope
|
//~^ ERROR cannot find attribute `unknown` in this scope
|
||||||
|
|
||||||
struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
|
struct WhereNo where for<#[cfg_attr(FALSE, unknown)] 'a> u8: Copy; // OK
|
||||||
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
|
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
|
||||||
//~^ ERROR cannot find attribute `unknown` in this scope
|
//~^ ERROR cannot find attribute `unknown` in this scope
|
||||||
|
|
||||||
|
|
|
@ -29,35 +29,35 @@ LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0658]: only lifetime parameters can be used in this context
|
error[E0658]: only lifetime parameters can be used in this context
|
||||||
--> $DIR/cfg-generic-params.rs:7:45
|
--> $DIR/cfg-generic-params.rs:7:48
|
||||||
|
|
|
|
||||||
LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
|
LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn();
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: only lifetime parameters can be used in this context
|
error[E0658]: only lifetime parameters can be used in this context
|
||||||
--> $DIR/cfg-generic-params.rs:11:51
|
--> $DIR/cfg-generic-params.rs:11:54
|
||||||
|
|
|
|
||||||
LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
|
LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy;
|
||||||
| ^
|
|
||||||
|
|
|
||||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
|
||||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error[E0658]: only lifetime parameters can be used in this context
|
|
||||||
--> $DIR/cfg-generic-params.rs:15:54
|
|
||||||
|
|
|
||||||
LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
|
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: only lifetime parameters can be used in this context
|
||||||
|
--> $DIR/cfg-generic-params.rs:15:57
|
||||||
|
|
|
||||||
|
LL | struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
|
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// we use a single revision because this should have a `full` revision
|
// we use a single revision because this should have a `full` revision
|
||||||
// but right now that ICEs and I(@BoxyUwU) could not get stderr normalization to work
|
// but right now that ICEs and I(@BoxyUwU) could not get stderr normalization to work
|
||||||
|
|
||||||
#![cfg_attr(full, feature(generic_const_exprs))]
|
// #![cfg_attr(full, feature(generic_const_exprs))]
|
||||||
#![cfg_attr(full, allow(incomplete_features))]
|
// #![cfg_attr(full, allow(incomplete_features))]
|
||||||
|
|
||||||
const fn foo<T>() -> usize { std::mem::size_of::<T>() }
|
const fn foo<T>() -> usize { std::mem::size_of::<T>() }
|
||||||
const fn bar<const N: usize>() -> usize { N }
|
const fn bar<const N: usize>() -> usize { N }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//@ compile-flags: --edition 2021
|
//@ compile-flags: --edition 2021
|
||||||
|
|
||||||
pub fn demo() -> Option<i32> {
|
pub fn demo() -> Option<i32> {
|
||||||
#[cfg(nope)]
|
#[cfg(FALSE)]
|
||||||
{
|
{
|
||||||
do yeet //~ ERROR `do yeet` expression is experimental
|
do yeet //~ ERROR `do yeet` expression is experimental
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ pub fn demo() -> Option<i32> {
|
||||||
Some(1)
|
Some(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nope)]
|
#[cfg(FALSE)]
|
||||||
pub fn alternative() -> Result<(), String> {
|
pub fn alternative() -> Result<(), String> {
|
||||||
do yeet "hello"; //~ ERROR `do yeet` expression is experimental
|
do yeet "hello"; //~ ERROR `do yeet` expression is experimental
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#![warn(unused_lifetimes)]
|
#![warn(unused_lifetimes, redundant_lifetimes)]
|
||||||
|
|
||||||
pub trait X {
|
pub trait X {
|
||||||
type Y<'a: 'static>;
|
type Y<'a: 'static>; //~ WARN unnecessary lifetime parameter `'a`
|
||||||
//~^ WARNING unnecessary lifetime parameter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X for () {
|
impl X for () {
|
||||||
|
|
|
@ -1,18 +1,5 @@
|
||||||
warning: unnecessary lifetime parameter `'a`
|
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:4:12
|
|
||||||
|
|
|
||||||
LL | type Y<'a: 'static>;
|
|
||||||
| ^^
|
|
||||||
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:1:9
|
|
||||||
|
|
|
||||||
LL | #![warn(unused_lifetimes)]
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:9:18
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:8:18
|
||||||
|
|
|
|
||||||
LL | type Y<'a: 'static>;
|
LL | type Y<'a: 'static>;
|
||||||
| ------------------- definition of `Y` from trait
|
| ------------------- definition of `Y` from trait
|
||||||
|
@ -21,7 +8,7 @@ LL | type Y<'a> = &'a ();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:9:12
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:8:12
|
||||||
|
|
|
|
||||||
LL | type Y<'a> = &'a ();
|
LL | type Y<'a> = &'a ();
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -32,44 +19,57 @@ LL | type Y<'a> = &'a () where 'a: 'static;
|
||||||
| +++++++++++++++++
|
| +++++++++++++++++
|
||||||
|
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:14:8
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:13:8
|
||||||
|
|
|
|
||||||
LL | f: <T as X>::Y<'a>,
|
LL | f: <T as X>::Y<'a>,
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:13:10
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:12:10
|
||||||
|
|
|
|
||||||
LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
|
LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
|
||||||
| ^^
|
| ^^
|
||||||
= note: but lifetime parameter must outlive the static lifetime
|
= note: but lifetime parameter must outlive the static lifetime
|
||||||
|
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:19:8
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:18:8
|
||||||
|
|
|
|
||||||
LL | f: <T as X>::Y<'a>,
|
LL | f: <T as X>::Y<'a>,
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:18:10
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:17:10
|
||||||
|
|
|
|
||||||
LL | struct C<'a, T: X> {
|
LL | struct C<'a, T: X> {
|
||||||
| ^^
|
| ^^
|
||||||
= note: but lifetime parameter must outlive the static lifetime
|
= note: but lifetime parameter must outlive the static lifetime
|
||||||
|
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:24:8
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:23:8
|
||||||
|
|
|
|
||||||
LL | f: <() as X>::Y<'a>,
|
LL | f: <() as X>::Y<'a>,
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
--> $DIR/unsatisfied-item-lifetime-bound.rs:23:10
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:22:10
|
||||||
|
|
|
|
||||||
LL | struct D<'a> {
|
LL | struct D<'a> {
|
||||||
| ^^
|
| ^^
|
||||||
= note: but lifetime parameter must outlive the static lifetime
|
= note: but lifetime parameter must outlive the static lifetime
|
||||||
|
|
||||||
|
warning: unnecessary lifetime parameter `'a`
|
||||||
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:4:12
|
||||||
|
|
|
||||||
|
LL | type Y<'a: 'static>;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unsatisfied-item-lifetime-bound.rs:1:27
|
||||||
|
|
|
||||||
|
LL | #![warn(unused_lifetimes, redundant_lifetimes)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 4 previous errors; 1 warning emitted
|
error: aborting due to 4 previous errors; 1 warning emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0478`.
|
For more information about this error, try `rustc --explain E0478`.
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
// Derive helpers are resolved successfully inside `cfg_attr`.
|
// Derive helpers are resolved successfully inside `cfg_attr`.
|
||||||
|
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
// compile-flats:--cfg TRUE
|
|
||||||
//@ aux-build:test-macros.rs
|
//@ aux-build:test-macros.rs
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate test_macros;
|
extern crate test_macros;
|
||||||
|
|
||||||
#[cfg_attr(TRUE, empty_helper)]
|
|
||||||
#[derive(Empty)]
|
#[derive(Empty)]
|
||||||
#[cfg_attr(TRUE, empty_helper)]
|
#[cfg_attr(all(), empty_helper)]
|
||||||
struct S {
|
struct S {
|
||||||
#[cfg_attr(TRUE, empty_helper)]
|
#[cfg_attr(all(), empty_helper)]
|
||||||
field: u8,
|
field: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
//
|
//
|
||||||
// 'a : 'b
|
// 'a : 'b
|
||||||
|
|
||||||
#![warn(unused_lifetimes)]
|
#![warn(redundant_lifetimes)]
|
||||||
|
|
||||||
fn test<'a,'b>(x: &'a i32) -> &'b i32
|
fn test<'a,'b>(x: &'a i32) -> &'b i32 //~ WARN unnecessary lifetime parameter `'a`
|
||||||
where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
|
where 'a: 'static
|
||||||
{
|
{
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
warning: unnecessary lifetime parameter `'a`
|
warning: unnecessary lifetime parameter `'a`
|
||||||
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:14:11
|
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:13:9
|
||||||
|
|
|
|
||||||
LL | where 'a: 'static
|
LL | fn test<'a,'b>(x: &'a i32) -> &'b i32
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:11:9
|
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:11:9
|
||||||
|
|
|
|
||||||
LL | #![warn(unused_lifetimes)]
|
LL | #![warn(redundant_lifetimes)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
|
|
||||||
#![warn(unused_lifetimes)]
|
#![warn(redundant_lifetimes)]
|
||||||
|
|
||||||
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
|
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
|
||||||
where 'a: 'static { t }
|
|
||||||
//~^ WARN unnecessary lifetime parameter `'a`
|
//~^ WARN unnecessary lifetime parameter `'a`
|
||||||
|
where 'a: 'static { t }
|
||||||
|
|
||||||
fn static_id<'a>(t: &'a ()) -> &'static ()
|
fn static_id<'a>(t: &'a ()) -> &'static ()
|
||||||
where 'a: 'static { t }
|
|
||||||
//~^ WARN unnecessary lifetime parameter `'a`
|
//~^ WARN unnecessary lifetime parameter `'a`
|
||||||
|
where 'a: 'static { t }
|
||||||
|
|
||||||
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
|
//~^ WARN unnecessary lifetime parameter `'a`
|
||||||
|
//~| WARN unnecessary lifetime parameter `'b`
|
||||||
where 'a: 'b, 'b: 'static { t }
|
where 'a: 'b, 'b: 'static { t }
|
||||||
//~^ WARN unnecessary lifetime parameter `'b`
|
|
||||||
|
|
||||||
fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t }
|
fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t }
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,39 @@
|
||||||
warning: unnecessary lifetime parameter `'a`
|
warning: unnecessary lifetime parameter `'a`
|
||||||
--> $DIR/regions-static-bound-rpass.rs:6:11
|
--> $DIR/regions-static-bound-rpass.rs:5:17
|
||||||
|
|
|
|
||||||
LL | where 'a: 'static { t }
|
LL | fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/regions-static-bound-rpass.rs:3:9
|
--> $DIR/regions-static-bound-rpass.rs:3:9
|
||||||
|
|
|
|
||||||
LL | #![warn(unused_lifetimes)]
|
LL | #![warn(redundant_lifetimes)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: unnecessary lifetime parameter `'a`
|
warning: unnecessary lifetime parameter `'a`
|
||||||
--> $DIR/regions-static-bound-rpass.rs:10:11
|
--> $DIR/regions-static-bound-rpass.rs:9:14
|
||||||
|
|
|
|
||||||
LL | where 'a: 'static { t }
|
LL | fn static_id<'a>(t: &'a ()) -> &'static ()
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
|
||||||
|
warning: unnecessary lifetime parameter `'a`
|
||||||
|
--> $DIR/regions-static-bound-rpass.rs:13:23
|
||||||
|
|
|
||||||
|
LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
|
||||||
warning: unnecessary lifetime parameter `'b`
|
warning: unnecessary lifetime parameter `'b`
|
||||||
--> $DIR/regions-static-bound-rpass.rs:14:19
|
--> $DIR/regions-static-bound-rpass.rs:13:26
|
||||||
|
|
|
|
||||||
LL | where 'a: 'b, 'b: 'static { t }
|
LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'b`
|
= note: you can use the `'static` lifetime directly, in place of `'b`
|
||||||
|
|
||||||
warning: 3 warnings emitted
|
warning: 4 warnings emitted
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#![warn(unused_lifetimes)]
|
#![warn(unused_lifetimes, redundant_lifetimes)]
|
||||||
|
|
||||||
fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
|
fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
|
||||||
//~^ WARN lifetime parameter `'b` never used
|
//~^ WARN unnecessary lifetime parameter `'a`
|
||||||
//~| WARN unnecessary lifetime parameter `'a`
|
//~| WARN lifetime parameter `'b` never used
|
||||||
|
|
||||||
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
|
//~^ WARN unnecessary lifetime parameter `'a`
|
||||||
|
//~| WARN unnecessary lifetime parameter `'b`
|
||||||
where 'a: 'b, 'b: 'static { t }
|
where 'a: 'b, 'b: 'static { t }
|
||||||
//~^ WARN unnecessary lifetime parameter `'b`
|
|
||||||
|
|
||||||
fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
|
fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
|
||||||
t
|
t
|
||||||
|
|
|
@ -9,27 +9,40 @@ LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/regions-static-bound.rs:1:9
|
--> $DIR/regions-static-bound.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![warn(unused_lifetimes)]
|
LL | #![warn(unused_lifetimes, redundant_lifetimes)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: unnecessary lifetime parameter `'a`
|
warning: unnecessary lifetime parameter `'a`
|
||||||
--> $DIR/regions-static-bound.rs:3:53
|
--> $DIR/regions-static-bound.rs:3:14
|
||||||
|
|
|
|
||||||
LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
|
LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/regions-static-bound.rs:1:27
|
||||||
|
|
|
||||||
|
LL | #![warn(unused_lifetimes, redundant_lifetimes)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unnecessary lifetime parameter `'a`
|
||||||
|
--> $DIR/regions-static-bound.rs:7:23
|
||||||
|
|
|
||||||
|
LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
|
||||||
warning: unnecessary lifetime parameter `'b`
|
warning: unnecessary lifetime parameter `'b`
|
||||||
--> $DIR/regions-static-bound.rs:8:19
|
--> $DIR/regions-static-bound.rs:7:26
|
||||||
|
|
|
|
||||||
LL | where 'a: 'b, 'b: 'static { t }
|
LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: you can use the `'static` lifetime directly, in place of `'b`
|
= note: you can use the `'static` lifetime directly, in place of `'b`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/regions-static-bound.rs:12:5
|
--> $DIR/regions-static-bound.rs:13:5
|
||||||
|
|
|
|
||||||
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -37,7 +50,7 @@ LL | t
|
||||||
| ^ returning this value requires that `'a` must outlive `'static`
|
| ^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/regions-static-bound.rs:17:5
|
--> $DIR/regions-static-bound.rs:18:5
|
||||||
|
|
|
|
||||||
LL | fn error(u: &(), v: &()) {
|
LL | fn error(u: &(), v: &()) {
|
||||||
| - - let's call the lifetime of this reference `'1`
|
| - - let's call the lifetime of this reference `'1`
|
||||||
|
@ -50,7 +63,7 @@ LL | static_id(&u);
|
||||||
| argument requires that `'1` must outlive `'static`
|
| argument requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/regions-static-bound.rs:19:5
|
--> $DIR/regions-static-bound.rs:20:5
|
||||||
|
|
|
|
||||||
LL | fn error(u: &(), v: &()) {
|
LL | fn error(u: &(), v: &()) {
|
||||||
| - - let's call the lifetime of this reference `'2`
|
| - - let's call the lifetime of this reference `'2`
|
||||||
|
@ -63,6 +76,6 @@ LL | static_id_indirect(&v);
|
||||||
| `v` escapes the function body here
|
| `v` escapes the function body here
|
||||||
| argument requires that `'2` must outlive `'static`
|
| argument requires that `'2` must outlive `'static`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors; 3 warnings emitted
|
error: aborting due to 3 previous errors; 4 warnings emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0521`.
|
For more information about this error, try `rustc --explain E0521`.
|
||||||
|
|
20
tests/ui/regions/transitively-redundant-lifetimes.rs
Normal file
20
tests/ui/regions/transitively-redundant-lifetimes.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#![deny(redundant_lifetimes)]
|
||||||
|
|
||||||
|
fn a<'a, 'b>(x: &'a &'b &'a ()) {} //~ ERROR unnecessary lifetime parameter `'b`
|
||||||
|
|
||||||
|
fn b<'a: 'b, 'b: 'a>() {} //~ ERROR unnecessary lifetime parameter `'b`
|
||||||
|
|
||||||
|
struct Foo<T: 'static>(T);
|
||||||
|
fn c<'a>(_: Foo<&'a ()>) {} //~ ERROR unnecessary lifetime parameter `'a`
|
||||||
|
|
||||||
|
struct Bar<'a>(&'a ());
|
||||||
|
impl<'a> Bar<'a> {
|
||||||
|
fn d<'b: 'a>(&'b self) {} //~ ERROR unnecessary lifetime parameter `'b`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ok(x: &'static &()) {}
|
||||||
|
|
||||||
|
trait Tr<'a> {}
|
||||||
|
impl<'a: 'static> Tr<'a> for () {} //~ ERROR unnecessary lifetime parameter `'a`
|
||||||
|
|
||||||
|
fn main() {}
|
47
tests/ui/regions/transitively-redundant-lifetimes.stderr
Normal file
47
tests/ui/regions/transitively-redundant-lifetimes.stderr
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
error: unnecessary lifetime parameter `'b`
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:3:10
|
||||||
|
|
|
||||||
|
LL | fn a<'a, 'b>(x: &'a &'b &'a ()) {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'a` lifetime directly, in place of `'b`
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(redundant_lifetimes)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unnecessary lifetime parameter `'b`
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:5:14
|
||||||
|
|
|
||||||
|
LL | fn b<'a: 'b, 'b: 'a>() {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'a` lifetime directly, in place of `'b`
|
||||||
|
|
||||||
|
error: unnecessary lifetime parameter `'a`
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:8:6
|
||||||
|
|
|
||||||
|
LL | fn c<'a>(_: Foo<&'a ()>) {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
|
||||||
|
error: unnecessary lifetime parameter `'a`
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:18:6
|
||||||
|
|
|
||||||
|
LL | impl<'a: 'static> Tr<'a> for () {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'static` lifetime directly, in place of `'a`
|
||||||
|
|
||||||
|
error: unnecessary lifetime parameter `'b`
|
||||||
|
--> $DIR/transitively-redundant-lifetimes.rs:12:10
|
||||||
|
|
|
||||||
|
LL | fn d<'b: 'a>(&'b self) {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: you can use the `'a` lifetime directly, in place of `'b`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//@ known-bug: #110395
|
//@ known-bug: #110395
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
// #![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||||
|
|
||||||
use std::marker::{Destruct, PhantomData};
|
use std::marker::{Destruct, PhantomData};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@ aux-build:edition-lint-paths.rs
|
//@ aux-build:edition-lint-paths.rs
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
//@ compile-flags:--extern edition_lint_paths --cfg blandiloquence
|
//@ compile-flags:--extern edition_lint_paths
|
||||||
//@ edition:2018
|
//@ edition:2018
|
||||||
|
|
||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@ aux-build:edition-lint-paths.rs
|
//@ aux-build:edition-lint-paths.rs
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
//@ compile-flags:--extern edition_lint_paths --cfg blandiloquence
|
//@ compile-flags:--extern edition_lint_paths
|
||||||
//@ edition:2018
|
//@ edition:2018
|
||||||
|
|
||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
// The suggestion span should include the attribute.
|
// The suggestion span should include the attribute.
|
||||||
|
|
||||||
#[cfg(blandiloquence)] //~ HELP remove it
|
#[cfg(not(FALSE))] //~ HELP remove it
|
||||||
extern crate edition_lint_paths;
|
extern crate edition_lint_paths;
|
||||||
//~^ ERROR unused extern crate
|
//~^ ERROR unused extern crate
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error: unused extern crate
|
error: unused extern crate
|
||||||
--> $DIR/issue-54400-unused-extern-crate-attr-span.rs:12:1
|
--> $DIR/issue-54400-unused-extern-crate-attr-span.rs:12:1
|
||||||
|
|
|
|
||||||
LL | / #[cfg(blandiloquence)]
|
LL | / #[cfg(not(FALSE))]
|
||||||
LL | | extern crate edition_lint_paths;
|
LL | | extern crate edition_lint_paths;
|
||||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
|
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||||
| |________________________________|
|
| |________________________________|
|
||||||
|
|
13
tests/ui/type/pattern_types/const_generics.rs
Normal file
13
tests/ui/type/pattern_types/const_generics.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(pattern_types)]
|
||||||
|
#![feature(core_pattern_types)]
|
||||||
|
#![feature(core_pattern_type)]
|
||||||
|
|
||||||
|
use std::pat::pattern_type;
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl<const START: u32, const END: u32> Foo for pattern_type!(u32 is START..=END) {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Reference in a new issue