mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #136918 - GuillaumeGomez:rollup-f6h21gg, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #134981 ( Explain that in paths generics can't be set on both the enum and the variant) - #136698 (Replace i686-unknown-redox target with i586-unknown-redox) - #136767 (improve host/cross target checking) - #136829 ([rustdoc] Move line numbers into the `<code>` directly) - #136875 (Rustc dev guide subtree update) - #136900 (compiler: replace `ExternAbi::name` calls with formatters) - #136913 (Put kobzol back on review rotation) - #136915 (documentation fix: `f16` and `f128` are not double-precision) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
552a959051
@ -367,9 +367,7 @@ fn push_debuginfo_type_name<'tcx>(
|
|||||||
output.push_str(sig.safety.prefix_str());
|
output.push_str(sig.safety.prefix_str());
|
||||||
|
|
||||||
if sig.abi != rustc_abi::ExternAbi::Rust {
|
if sig.abi != rustc_abi::ExternAbi::Rust {
|
||||||
output.push_str("extern \"");
|
let _ = write!(output, "extern {} ", sig.abi);
|
||||||
output.push_str(sig.abi.name());
|
|
||||||
output.push_str("\" ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push_str("fn(");
|
output.push_str("fn(");
|
||||||
|
@ -93,6 +93,7 @@ into_diag_arg_using_display!(
|
|||||||
SplitDebuginfo,
|
SplitDebuginfo,
|
||||||
ExitStatus,
|
ExitStatus,
|
||||||
ErrCode,
|
ErrCode,
|
||||||
|
rustc_abi::ExternAbi,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
|
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
|
||||||
|
@ -72,17 +72,17 @@ hir_analysis_cmse_entry_generic =
|
|||||||
functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
|
functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
|
||||||
|
|
||||||
hir_analysis_cmse_inputs_stack_spill =
|
hir_analysis_cmse_inputs_stack_spill =
|
||||||
arguments for `"{$abi_name}"` function too large to pass via registers
|
arguments for `{$abi}` function too large to pass via registers
|
||||||
.label = {$plural ->
|
.label = {$plural ->
|
||||||
[false] this argument doesn't
|
[false] this argument doesn't
|
||||||
*[true] these arguments don't
|
*[true] these arguments don't
|
||||||
} fit in the available registers
|
} fit in the available registers
|
||||||
.note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers
|
.note = functions with the `{$abi}` ABI must pass all their arguments via the 4 32-bit available argument registers
|
||||||
|
|
||||||
hir_analysis_cmse_output_stack_spill =
|
hir_analysis_cmse_output_stack_spill =
|
||||||
return value of `"{$abi_name}"` function too large to pass via registers
|
return value of `{$abi}` function too large to pass via registers
|
||||||
.label = this type doesn't fit in the available registers
|
.label = this type doesn't fit in the available registers
|
||||||
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
|
.note1 = functions with the `{$abi}` ABI must pass their result via the available return registers
|
||||||
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||||
|
|
||||||
hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
|
hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
|
||||||
|
@ -614,9 +614,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||||||
if !infer_replacements.is_empty() {
|
if !infer_replacements.is_empty() {
|
||||||
diag.multipart_suggestion(
|
diag.multipart_suggestion(
|
||||||
format!(
|
format!(
|
||||||
"try replacing `_` with the type{} in the corresponding trait method signature",
|
"try replacing `_` with the type{} in the corresponding trait method \
|
||||||
rustc_errors::pluralize!(infer_replacements.len()),
|
signature",
|
||||||
),
|
rustc_errors::pluralize!(infer_replacements.len()),
|
||||||
|
),
|
||||||
infer_replacements,
|
infer_replacements,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Errors emitted by `rustc_hir_analysis`.
|
//! Errors emitted by `rustc_hir_analysis`.
|
||||||
|
|
||||||
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
|
Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
|
||||||
@ -1690,7 +1691,7 @@ pub(crate) struct CmseInputsStackSpill {
|
|||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub plural: bool,
|
pub plural: bool,
|
||||||
pub abi_name: &'static str,
|
pub abi: ExternAbi,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
@ -1701,7 +1702,7 @@ pub(crate) struct CmseOutputStackSpill {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub abi_name: &'static str,
|
pub abi: ExternAbi,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -17,8 +17,6 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||||||
abi: ExternAbi,
|
abi: ExternAbi,
|
||||||
fn_sig: ty::PolyFnSig<'tcx>,
|
fn_sig: ty::PolyFnSig<'tcx>,
|
||||||
) {
|
) {
|
||||||
let abi_name = abi.name();
|
|
||||||
|
|
||||||
match abi {
|
match abi {
|
||||||
ExternAbi::CCmseNonSecureCall => {
|
ExternAbi::CCmseNonSecureCall => {
|
||||||
let hir_node = tcx.hir_node(hir_id);
|
let hir_node = tcx.hir_node(hir_id);
|
||||||
@ -56,7 +54,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||||||
.to(bare_fn_ty.decl.inputs[index].span)
|
.to(bare_fn_ty.decl.inputs[index].span)
|
||||||
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
||||||
let plural = bare_fn_ty.param_names.len() - index != 1;
|
let plural = bare_fn_ty.param_names.len() - index != 1;
|
||||||
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
|
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
|
||||||
}
|
}
|
||||||
Err(layout_err) => {
|
Err(layout_err) => {
|
||||||
if should_emit_generic_error(abi, layout_err) {
|
if should_emit_generic_error(abi, layout_err) {
|
||||||
@ -69,7 +67,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
Ok(false) => {
|
Ok(false) => {
|
||||||
let span = bare_fn_ty.decl.output.span();
|
let span = bare_fn_ty.decl.output.span();
|
||||||
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
|
dcx.emit_err(errors::CmseOutputStackSpill { span, abi });
|
||||||
}
|
}
|
||||||
Err(layout_err) => {
|
Err(layout_err) => {
|
||||||
if should_emit_generic_error(abi, layout_err) {
|
if should_emit_generic_error(abi, layout_err) {
|
||||||
@ -92,7 +90,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||||||
// ^^^^^^
|
// ^^^^^^
|
||||||
let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span);
|
let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span);
|
||||||
let plural = decl.inputs.len() - index != 1;
|
let plural = decl.inputs.len() - index != 1;
|
||||||
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
|
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
|
||||||
}
|
}
|
||||||
Err(layout_err) => {
|
Err(layout_err) => {
|
||||||
if should_emit_generic_error(abi, layout_err) {
|
if should_emit_generic_error(abi, layout_err) {
|
||||||
@ -105,7 +103,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
Ok(false) => {
|
Ok(false) => {
|
||||||
let span = decl.output.span();
|
let span = decl.output.span();
|
||||||
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
|
dcx.emit_err(errors::CmseOutputStackSpill { span, abi });
|
||||||
}
|
}
|
||||||
Err(layout_err) => {
|
Err(layout_err) => {
|
||||||
if should_emit_generic_error(abi, layout_err) {
|
if should_emit_generic_error(abi, layout_err) {
|
||||||
|
@ -6,7 +6,7 @@ use rustc_errors::{
|
|||||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err,
|
Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||||
@ -1027,7 +1027,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
&self,
|
&self,
|
||||||
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
||||||
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
|
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
|
||||||
err_extend: GenericsArgsErrExtend<'_>,
|
err_extend: GenericsArgsErrExtend<'a>,
|
||||||
) -> ErrorGuaranteed {
|
) -> ErrorGuaranteed {
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
enum ProhibitGenericsArg {
|
enum ProhibitGenericsArg {
|
||||||
@ -1047,23 +1047,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let segments: Vec<_> = segments.collect();
|
||||||
let types_and_spans: Vec<_> = segments
|
let types_and_spans: Vec<_> = segments
|
||||||
.clone()
|
.iter()
|
||||||
.flat_map(|segment| {
|
.flat_map(|segment| {
|
||||||
if segment.args().args.is_empty() {
|
if segment.args().args.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((
|
Some((
|
||||||
match segment.res {
|
match segment.res {
|
||||||
hir::def::Res::PrimTy(ty) => {
|
Res::PrimTy(ty) => {
|
||||||
format!("{} `{}`", segment.res.descr(), ty.name())
|
format!("{} `{}`", segment.res.descr(), ty.name())
|
||||||
}
|
}
|
||||||
hir::def::Res::Def(_, def_id)
|
Res::Def(_, def_id)
|
||||||
if let Some(name) = self.tcx().opt_item_name(def_id) =>
|
if let Some(name) = self.tcx().opt_item_name(def_id) =>
|
||||||
{
|
{
|
||||||
format!("{} `{name}`", segment.res.descr())
|
format!("{} `{name}`", segment.res.descr())
|
||||||
}
|
}
|
||||||
hir::def::Res::Err => "this type".to_string(),
|
Res::Err => "this type".to_string(),
|
||||||
_ => segment.res.descr().to_string(),
|
_ => segment.res.descr().to_string(),
|
||||||
},
|
},
|
||||||
segment.ident.span,
|
segment.ident.span,
|
||||||
@ -1074,11 +1075,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
|
let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
|
||||||
.expect("expected one segment to deny");
|
.expect("expected one segment to deny");
|
||||||
|
|
||||||
let arg_spans: Vec<Span> = segments
|
let arg_spans: Vec<Span> =
|
||||||
.clone()
|
segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
|
||||||
.flat_map(|segment| segment.args().args)
|
|
||||||
.map(|arg| arg.span())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut kinds = Vec::with_capacity(4);
|
let mut kinds = Vec::with_capacity(4);
|
||||||
prohibit_args.iter().for_each(|arg| match arg {
|
prohibit_args.iter().for_each(|arg| match arg {
|
||||||
@ -1103,7 +1101,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
for (what, span) in types_and_spans {
|
for (what, span) in types_and_spans {
|
||||||
err.span_label(span, format!("not allowed on {what}"));
|
err.span_label(span, format!("not allowed on {what}"));
|
||||||
}
|
}
|
||||||
generics_args_err_extend(self.tcx(), segments, &mut err, err_extend);
|
generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
|
||||||
err.emit()
|
err.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,7 +1398,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
|
|||||||
},
|
},
|
||||||
SelfTyParam(Span),
|
SelfTyParam(Span),
|
||||||
Param(DefId),
|
Param(DefId),
|
||||||
DefVariant,
|
DefVariant(&'tcx [hir::PathSegment<'tcx>]),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1408,7 +1406,7 @@ fn generics_args_err_extend<'a>(
|
|||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
err_extend: GenericsArgsErrExtend<'_>,
|
err_extend: GenericsArgsErrExtend<'a>,
|
||||||
) {
|
) {
|
||||||
match err_extend {
|
match err_extend {
|
||||||
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
|
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
|
||||||
@ -1496,6 +1494,32 @@ fn generics_args_err_extend<'a>(
|
|||||||
];
|
];
|
||||||
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
|
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
|
||||||
}
|
}
|
||||||
|
GenericsArgsErrExtend::DefVariant(segments) => {
|
||||||
|
let args: Vec<Span> = segments
|
||||||
|
.iter()
|
||||||
|
.filter_map(|segment| match segment.res {
|
||||||
|
Res::Def(
|
||||||
|
DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
|
||||||
|
_,
|
||||||
|
) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if args.len() > 1
|
||||||
|
&& let Some(span) = args.into_iter().last()
|
||||||
|
{
|
||||||
|
err.note(
|
||||||
|
"generic arguments are not allowed on both an enum and its variant's path \
|
||||||
|
segments simultaneously; they are only valid in one place or the other",
|
||||||
|
);
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
"remove the generics arguments from one of the path segments",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
GenericsArgsErrExtend::PrimTy(prim_ty) => {
|
GenericsArgsErrExtend::PrimTy(prim_ty) => {
|
||||||
let name = prim_ty.name_str();
|
let name = prim_ty.name_str();
|
||||||
for segment in segments {
|
for segment in segments {
|
||||||
@ -1512,9 +1536,6 @@ fn generics_args_err_extend<'a>(
|
|||||||
GenericsArgsErrExtend::OpaqueTy => {
|
GenericsArgsErrExtend::OpaqueTy => {
|
||||||
err.note("`impl Trait` types can't have type parameters");
|
err.note("`impl Trait` types can't have type parameters");
|
||||||
}
|
}
|
||||||
GenericsArgsErrExtend::DefVariant => {
|
|
||||||
err.note("enum variants can't have type parameters");
|
|
||||||
}
|
|
||||||
GenericsArgsErrExtend::Param(def_id) => {
|
GenericsArgsErrExtend::Param(def_id) => {
|
||||||
let span = tcx.def_ident_span(def_id).unwrap();
|
let span = tcx.def_ident_span(def_id).unwrap();
|
||||||
let kind = tcx.def_descr(def_id);
|
let kind = tcx.def_descr(def_id);
|
||||||
|
@ -1694,7 +1694,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
pub fn prohibit_generic_args<'a>(
|
pub fn prohibit_generic_args<'a>(
|
||||||
&self,
|
&self,
|
||||||
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
||||||
err_extend: GenericsArgsErrExtend<'_>,
|
err_extend: GenericsArgsErrExtend<'a>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
|
let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
|
||||||
let mut result = Ok(());
|
let mut result = Ok(());
|
||||||
@ -1911,7 +1911,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
path.segments.iter().enumerate().filter_map(|(index, seg)| {
|
path.segments.iter().enumerate().filter_map(|(index, seg)| {
|
||||||
if !indices.contains(&index) { Some(seg) } else { None }
|
if !indices.contains(&index) { Some(seg) } else { None }
|
||||||
}),
|
}),
|
||||||
GenericsArgsErrExtend::DefVariant,
|
GenericsArgsErrExtend::DefVariant(&path.segments),
|
||||||
);
|
);
|
||||||
|
|
||||||
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
||||||
|
@ -1043,12 +1043,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let mut user_self_ty = None;
|
let mut user_self_ty = None;
|
||||||
let mut is_alias_variant_ctor = false;
|
let mut is_alias_variant_ctor = false;
|
||||||
|
let mut err_extend = GenericsArgsErrExtend::None;
|
||||||
match res {
|
match res {
|
||||||
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => {
|
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => {
|
||||||
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
|
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
|
||||||
user_self_ty =
|
user_self_ty =
|
||||||
Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
|
Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
|
||||||
is_alias_variant_ctor = true;
|
is_alias_variant_ctor = true;
|
||||||
|
err_extend = GenericsArgsErrExtend::DefVariant(segments);
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
|
||||||
|
err_extend = GenericsArgsErrExtend::DefVariant(segments);
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
|
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
|
||||||
let assoc_item = tcx.associated_item(def_id);
|
let assoc_item = tcx.associated_item(def_id);
|
||||||
@ -1095,7 +1100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
segments.iter().enumerate().filter_map(|(index, seg)| {
|
segments.iter().enumerate().filter_map(|(index, seg)| {
|
||||||
if !indices.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None }
|
if !indices.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None }
|
||||||
}),
|
}),
|
||||||
GenericsArgsErrExtend::None,
|
err_extend,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Res::Local(hid) = res {
|
if let Res::Local(hid) = res {
|
||||||
|
@ -160,8 +160,7 @@ pub(super) fn decorate_lint(
|
|||||||
.decorate_lint(diag);
|
.decorate_lint(diag);
|
||||||
}
|
}
|
||||||
BuiltinLintDiag::MissingAbi(label_span, default_abi) => {
|
BuiltinLintDiag::MissingAbi(label_span, default_abi) => {
|
||||||
lints::MissingAbi { span: label_span, default_abi: default_abi.name() }
|
lints::MissingAbi { span: label_span, default_abi }.decorate_lint(diag);
|
||||||
.decorate_lint(diag);
|
|
||||||
}
|
}
|
||||||
BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
|
BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
|
||||||
lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
|
lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
|
Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
|
||||||
@ -2833,9 +2834,9 @@ pub(crate) struct PatternsInFnsWithoutBodySub {
|
|||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_extern_without_abi)]
|
#[diag(lint_extern_without_abi)]
|
||||||
pub(crate) struct MissingAbi {
|
pub(crate) struct MissingAbi {
|
||||||
#[suggestion(code = "extern \"{default_abi}\"", applicability = "machine-applicable")]
|
#[suggestion(code = "extern {default_abi}", applicability = "machine-applicable")]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub default_abi: &'static str,
|
pub default_abi: ExternAbi,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
|
@ -161,12 +161,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||||||
let unsafety = fn_sig.safety().prefix_str();
|
let unsafety = fn_sig.safety().prefix_str();
|
||||||
let abi = match fn_sig.abi() {
|
let abi = match fn_sig.abi() {
|
||||||
ExternAbi::Rust => String::from(""),
|
ExternAbi::Rust => String::from(""),
|
||||||
other_abi => {
|
other_abi => format!("extern {other_abi} "),
|
||||||
let mut s = String::from("extern \"");
|
|
||||||
s.push_str(other_abi.name());
|
|
||||||
s.push_str("\" ");
|
|
||||||
s
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let ident = self.tcx.item_ident(fn_id);
|
let ident = self.tcx.item_ident(fn_id);
|
||||||
let ty_params = fn_args.types().map(|ty| format!("{ty}"));
|
let ty_params = fn_args.types().map(|ty| format!("{ty}"));
|
||||||
|
@ -1790,7 +1790,7 @@ supported_targets! {
|
|||||||
("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
|
("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
|
||||||
|
|
||||||
("aarch64-unknown-redox", aarch64_unknown_redox),
|
("aarch64-unknown-redox", aarch64_unknown_redox),
|
||||||
("i686-unknown-redox", i686_unknown_redox),
|
("i586-unknown-redox", i586_unknown_redox),
|
||||||
("x86_64-unknown-redox", x86_64_unknown_redox),
|
("x86_64-unknown-redox", x86_64_unknown_redox),
|
||||||
|
|
||||||
("i386-apple-ios", i386_apple_ios),
|
("i386-apple-ios", i386_apple_ios),
|
||||||
|
@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
base.stack_probes = StackProbeType::Call;
|
base.stack_probes = StackProbeType::Call;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "i686-unknown-redox".into(),
|
llvm_target: "i586-unknown-redox".into(),
|
||||||
metadata: crate::spec::TargetMetadata {
|
metadata: crate::spec::TargetMetadata {
|
||||||
description: None,
|
description: None,
|
||||||
tier: None,
|
tier: None,
|
@ -1,4 +1,4 @@
|
|||||||
//! Constants for the `f128` double-precision floating point type.
|
//! Constants for the `f128` quadruple-precision floating point type.
|
||||||
//!
|
//!
|
||||||
//! *[See also the `f128` primitive type](primitive@f128).*
|
//! *[See also the `f128` primitive type](primitive@f128).*
|
||||||
//!
|
//!
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! Constants for the `f16` double-precision floating point type.
|
//! Constants for the `f16` half-precision floating point type.
|
||||||
//!
|
//!
|
||||||
//! *[See also the `f16` primitive type](primitive@f16).*
|
//! *[See also the `f16` primitive type](primitive@f16).*
|
||||||
//!
|
//!
|
||||||
|
@ -191,7 +191,7 @@ impl Step for Std {
|
|||||||
// The LLD wrappers and `rust-lld` are self-contained linking components that can be
|
// The LLD wrappers and `rust-lld` are self-contained linking components that can be
|
||||||
// necessary to link the stdlib on some targets. We'll also need to copy these binaries to
|
// necessary to link the stdlib on some targets. We'll also need to copy these binaries to
|
||||||
// the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
|
// the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
|
||||||
if compiler.stage == 0 && compiler.host == builder.config.build {
|
if compiler.stage == 0 && builder.is_builder_target(&compiler.host) {
|
||||||
// We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
|
// We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
|
||||||
let src_sysroot_bin = builder
|
let src_sysroot_bin = builder
|
||||||
.rustc_snapshot_sysroot()
|
.rustc_snapshot_sysroot()
|
||||||
@ -2310,7 +2310,8 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path)
|
|||||||
// FIXME: to make things simpler for now, limit this to the host and target where we know
|
// FIXME: to make things simpler for now, limit this to the host and target where we know
|
||||||
// `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not
|
// `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not
|
||||||
// cross-compiling. Expand this to other appropriate targets in the future.
|
// cross-compiling. Expand this to other appropriate targets in the future.
|
||||||
if target != "x86_64-unknown-linux-gnu" || target != builder.config.build || !path.exists() {
|
if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(&target) || !path.exists()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +582,7 @@ impl Step for DebuggerScripts {
|
|||||||
fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
|
fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
|
||||||
// The only true set of target libraries came from the build triple, so
|
// The only true set of target libraries came from the build triple, so
|
||||||
// let's reduce redundant work by only producing archives from that host.
|
// let's reduce redundant work by only producing archives from that host.
|
||||||
if compiler.host != builder.config.build {
|
if !builder.is_builder_target(&compiler.host) {
|
||||||
builder.info("\tskipping, not a build host");
|
builder.info("\tskipping, not a build host");
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -637,7 +637,7 @@ fn copy_target_libs(
|
|||||||
for (path, dependency_type) in builder.read_stamp_file(stamp) {
|
for (path, dependency_type) in builder.read_stamp_file(stamp) {
|
||||||
if dependency_type == DependencyType::TargetSelfContained {
|
if dependency_type == DependencyType::TargetSelfContained {
|
||||||
builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
|
builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
|
||||||
} else if dependency_type == DependencyType::Target || builder.config.build == target {
|
} else if dependency_type == DependencyType::Target || builder.is_builder_target(&target) {
|
||||||
builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
|
builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -786,7 +786,7 @@ impl Step for Analysis {
|
|||||||
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
|
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
|
||||||
let compiler = self.compiler;
|
let compiler = self.compiler;
|
||||||
let target = self.target;
|
let target = self.target;
|
||||||
if compiler.host != builder.config.build {
|
if !builder.is_builder_target(&compiler.host) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +516,7 @@ impl Step for Llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://llvm.org/docs/HowToCrossCompileLLVM.html
|
// https://llvm.org/docs/HowToCrossCompileLLVM.html
|
||||||
if target != builder.config.build {
|
if !builder.is_builder_target(&target) {
|
||||||
let LlvmResult { llvm_config, .. } =
|
let LlvmResult { llvm_config, .. } =
|
||||||
builder.ensure(Llvm { target: builder.config.build });
|
builder.ensure(Llvm { target: builder.config.build });
|
||||||
if !builder.config.dry_run() {
|
if !builder.config.dry_run() {
|
||||||
@ -661,7 +661,7 @@ fn configure_cmake(
|
|||||||
}
|
}
|
||||||
cfg.target(&target.triple).host(&builder.config.build.triple);
|
cfg.target(&target.triple).host(&builder.config.build.triple);
|
||||||
|
|
||||||
if target != builder.config.build {
|
if !builder.is_builder_target(&target) {
|
||||||
cfg.define("CMAKE_CROSSCOMPILING", "True");
|
cfg.define("CMAKE_CROSSCOMPILING", "True");
|
||||||
|
|
||||||
if target.contains("netbsd") {
|
if target.contains("netbsd") {
|
||||||
@ -1111,7 +1111,7 @@ impl Step for Lld {
|
|||||||
.define("LLVM_CMAKE_DIR", llvm_cmake_dir)
|
.define("LLVM_CMAKE_DIR", llvm_cmake_dir)
|
||||||
.define("LLVM_INCLUDE_TESTS", "OFF");
|
.define("LLVM_INCLUDE_TESTS", "OFF");
|
||||||
|
|
||||||
if target != builder.config.build {
|
if !builder.is_builder_target(&target) {
|
||||||
// Use the host llvm-tblgen binary.
|
// Use the host llvm-tblgen binary.
|
||||||
cfg.define(
|
cfg.define(
|
||||||
"LLVM_TABLEGEN_EXE",
|
"LLVM_TABLEGEN_EXE",
|
||||||
|
@ -2742,7 +2742,7 @@ impl Step for Crate {
|
|||||||
cargo
|
cargo
|
||||||
} else {
|
} else {
|
||||||
// Also prepare a sysroot for the target.
|
// Also prepare a sysroot for the target.
|
||||||
if builder.config.build != target {
|
if !builder.is_builder_target(&target) {
|
||||||
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
|
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
|
||||||
builder.ensure(RemoteCopyLibs { compiler, target });
|
builder.ensure(RemoteCopyLibs { compiler, target });
|
||||||
}
|
}
|
||||||
|
@ -1065,3 +1065,19 @@ fn test_prebuilt_llvm_config_path_resolution() {
|
|||||||
.join(exe("llvm-config", builder.config.build));
|
.join(exe("llvm-config", builder.config.build));
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_builder_target() {
|
||||||
|
let target1 = TargetSelection::from_user(TEST_TRIPLE_1);
|
||||||
|
let target2 = TargetSelection::from_user(TEST_TRIPLE_2);
|
||||||
|
|
||||||
|
for (target1, target2) in [(target1, target2), (target2, target1)] {
|
||||||
|
let mut config = configure("build", &[], &[]);
|
||||||
|
config.build = target1;
|
||||||
|
let build = Build::new(config);
|
||||||
|
let builder = Builder::new(&build);
|
||||||
|
|
||||||
|
assert!(builder.is_builder_target(&target1));
|
||||||
|
assert!(!builder.is_builder_target(&target2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -329,7 +329,7 @@ than building it.
|
|||||||
if target.contains("musl") && !target.contains("unikraft") {
|
if target.contains("musl") && !target.contains("unikraft") {
|
||||||
// If this is a native target (host is also musl) and no musl-root is given,
|
// If this is a native target (host is also musl) and no musl-root is given,
|
||||||
// fall back to the system toolchain in /usr before giving up
|
// fall back to the system toolchain in /usr before giving up
|
||||||
if build.musl_root(*target).is_none() && build.config.build == *target {
|
if build.musl_root(*target).is_none() && build.is_builder_target(target) {
|
||||||
let target = build.config.target_config.entry(*target).or_default();
|
let target = build.config.target_config.entry(*target).or_default();
|
||||||
target.musl_root = Some("/usr".into());
|
target.musl_root = Some("/usr".into());
|
||||||
}
|
}
|
||||||
|
@ -739,7 +739,7 @@ impl Build {
|
|||||||
/// Note that if LLVM is configured externally then the directory returned
|
/// Note that if LLVM is configured externally then the directory returned
|
||||||
/// will likely be empty.
|
/// will likely be empty.
|
||||||
fn llvm_out(&self, target: TargetSelection) -> PathBuf {
|
fn llvm_out(&self, target: TargetSelection) -> PathBuf {
|
||||||
if self.config.llvm_from_ci && self.config.build == target {
|
if self.config.llvm_from_ci && self.is_builder_target(&target) {
|
||||||
self.config.ci_llvm_root()
|
self.config.ci_llvm_root()
|
||||||
} else {
|
} else {
|
||||||
self.out.join(target).join("llvm")
|
self.out.join(target).join("llvm")
|
||||||
@ -789,7 +789,7 @@ impl Build {
|
|||||||
fn is_system_llvm(&self, target: TargetSelection) -> bool {
|
fn is_system_llvm(&self, target: TargetSelection) -> bool {
|
||||||
match self.config.target_config.get(&target) {
|
match self.config.target_config.get(&target) {
|
||||||
Some(Target { llvm_config: Some(_), .. }) => {
|
Some(Target { llvm_config: Some(_), .. }) => {
|
||||||
let ci_llvm = self.config.llvm_from_ci && target == self.config.build;
|
let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(&target);
|
||||||
!ci_llvm
|
!ci_llvm
|
||||||
}
|
}
|
||||||
// We're building from the in-tree src/llvm-project sources.
|
// We're building from the in-tree src/llvm-project sources.
|
||||||
@ -1274,7 +1274,7 @@ Executed at: {executed_at}"#,
|
|||||||
// need to use CXX compiler as linker to resolve the exception functions
|
// need to use CXX compiler as linker to resolve the exception functions
|
||||||
// that are only existed in CXX libraries
|
// that are only existed in CXX libraries
|
||||||
Some(self.cxx.borrow()[&target].path().into())
|
Some(self.cxx.borrow()[&target].path().into())
|
||||||
} else if target != self.config.build
|
} else if !self.is_builder_target(&target)
|
||||||
&& helpers::use_host_linker(target)
|
&& helpers::use_host_linker(target)
|
||||||
&& !target.is_msvc()
|
&& !target.is_msvc()
|
||||||
{
|
{
|
||||||
@ -1925,6 +1925,11 @@ to download LLVM rather than building it.
|
|||||||
stream.reset().unwrap();
|
stream.reset().unwrap();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the given target is the same as the builder target.
|
||||||
|
fn is_builder_target(&self, target: &TargetSelection) -> bool {
|
||||||
|
&self.config.build == target
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -3,8 +3,8 @@ name: rustc-pull
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
# Run at 04:00 UTC every Monday
|
# Run at 04:00 UTC every Monday and Thursday
|
||||||
- cron: '0 4 * * 1'
|
- cron: '0 4 * * 1,4'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pull:
|
pull:
|
||||||
@ -34,8 +34,25 @@ jobs:
|
|||||||
git config --global user.name 'The rustc-dev-guide Cronjob Bot'
|
git config --global user.name 'The rustc-dev-guide Cronjob Bot'
|
||||||
git config --global user.email 'github-actions@github.com'
|
git config --global user.email 'github-actions@github.com'
|
||||||
- name: Perform rustc-pull
|
- name: Perform rustc-pull
|
||||||
run: cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull
|
id: rustc-pull
|
||||||
|
# Turn off -e to disable early exit
|
||||||
|
shell: bash {0}
|
||||||
|
run: |
|
||||||
|
cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull
|
||||||
|
exitcode=$?
|
||||||
|
|
||||||
|
# If no pull was performed, we want to mark this job as successful,
|
||||||
|
# but we do not want to perform the follow-up steps.
|
||||||
|
if [ $exitcode -eq 0 ]; then
|
||||||
|
echo "pull_result=pull-finished" >> $GITHUB_OUTPUT
|
||||||
|
elif [ $exitcode -eq 2 ]; then
|
||||||
|
echo "pull_result=skipped" >> $GITHUB_OUTPUT
|
||||||
|
exitcode=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit ${exitcode}
|
||||||
- name: Push changes to a branch
|
- name: Push changes to a branch
|
||||||
|
if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }}
|
||||||
run: |
|
run: |
|
||||||
# Update a sticky branch that is used only for rustc pulls
|
# Update a sticky branch that is used only for rustc pulls
|
||||||
BRANCH="rustc-pull"
|
BRANCH="rustc-pull"
|
||||||
@ -43,6 +60,9 @@ jobs:
|
|||||||
git push -u origin $BRANCH --force
|
git push -u origin $BRANCH --force
|
||||||
- name: Create pull request
|
- name: Create pull request
|
||||||
id: update-pr
|
id: update-pr
|
||||||
|
if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
# Check if an open pull request for an rustc pull update already exists
|
# Check if an open pull request for an rustc pull update already exists
|
||||||
# If it does, the previous push has just updated it
|
# If it does, the previous push has just updated it
|
||||||
@ -54,26 +74,35 @@ jobs:
|
|||||||
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
|
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title`
|
PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title`
|
||||||
|
echo "Updating pull request ${PR_URL}"
|
||||||
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
|
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
send-zulip-message:
|
send-zulip-message:
|
||||||
needs: [pull]
|
needs: [pull]
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
- name: Compute message
|
- name: Compute message
|
||||||
id: message
|
id: create-message
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ needs.pull.result }}" == "failure" ];
|
if [ "${{ needs.pull.result }}" == "failure" ]; then
|
||||||
then
|
|
||||||
WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
echo "message=Rustc pull sync failed. Check out the [workflow URL]($WORKFLOW_URL)." >> $GITHUB_OUTPUT
|
echo "message=Rustc pull sync failed. Check out the [workflow URL]($WORKFLOW_URL)." >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "message=Rustc pull sync succeeded. Check out the [PR](${{ needs.pull.outputs.pr_url }})." >> $GITHUB_OUTPUT
|
CREATED_AT=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].createdAt' --json createdAt,title`
|
||||||
|
PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title`
|
||||||
|
week_ago=$(date +%F -d '7 days ago')
|
||||||
|
|
||||||
|
# If there is an open PR that is at least a week old, post a message about it
|
||||||
|
if [[ -n $DATE_GH && $DATE_GH < $week_ago ]]; then
|
||||||
|
echo "message=A PR with a Rustc pull has been opened for more a week. Check out the [PR](${PR_URL})." >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
- name: Send a Zulip message about updated PR
|
- name: Send a Zulip message about updated PR
|
||||||
|
if: ${{ steps.create-message.outputs.message != '' }}
|
||||||
uses: zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5
|
uses: zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5
|
||||||
with:
|
with:
|
||||||
api-key: ${{ secrets.ZULIP_API_TOKEN }}
|
api-key: ${{ secrets.ZULIP_API_TOKEN }}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use crate::sync::GitSync;
|
use crate::sync::{GitSync, RustcPullError};
|
||||||
|
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|
||||||
@ -22,7 +22,18 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let sync = GitSync::from_current_dir()?;
|
let sync = GitSync::from_current_dir()?;
|
||||||
match args {
|
match args {
|
||||||
Args::RustcPull => {
|
Args::RustcPull => {
|
||||||
sync.rustc_pull(None)?;
|
if let Err(error) = sync.rustc_pull(None) {
|
||||||
|
match error {
|
||||||
|
RustcPullError::NothingToPull => {
|
||||||
|
eprintln!("Nothing to pull");
|
||||||
|
std::process::exit(2);
|
||||||
|
}
|
||||||
|
RustcPullError::PullFailed(error) => {
|
||||||
|
eprintln!("Pull failure: {error:?}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Args::RustcPush { github_username, branch } => {
|
Args::RustcPush { github_username, branch } => {
|
||||||
sync.rustc_push(github_username, branch)?;
|
sync.rustc_push(github_username, branch)?;
|
||||||
|
@ -11,6 +11,19 @@ const JOSH_FILTER: &str = ":/src/doc/rustc-dev-guide";
|
|||||||
const JOSH_PORT: u16 = 42042;
|
const JOSH_PORT: u16 = 42042;
|
||||||
const UPSTREAM_REPO: &str = "rust-lang/rust";
|
const UPSTREAM_REPO: &str = "rust-lang/rust";
|
||||||
|
|
||||||
|
pub enum RustcPullError {
|
||||||
|
/// No changes are available to be pulled.
|
||||||
|
NothingToPull,
|
||||||
|
/// A rustc-pull has failed, probably a git operation error has occurred.
|
||||||
|
PullFailed(anyhow::Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> From<E> for RustcPullError where E: Into<anyhow::Error> {
|
||||||
|
fn from(error: E) -> Self {
|
||||||
|
Self::PullFailed(error.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GitSync {
|
pub struct GitSync {
|
||||||
dir: PathBuf,
|
dir: PathBuf,
|
||||||
}
|
}
|
||||||
@ -24,7 +37,7 @@ impl GitSync {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rustc_pull(&self, commit: Option<String>) -> anyhow::Result<()> {
|
pub fn rustc_pull(&self, commit: Option<String>) -> Result<(), RustcPullError> {
|
||||||
let sh = Shell::new()?;
|
let sh = Shell::new()?;
|
||||||
sh.change_dir(&self.dir);
|
sh.change_dir(&self.dir);
|
||||||
let commit = commit.map(Ok).unwrap_or_else(|| {
|
let commit = commit.map(Ok).unwrap_or_else(|| {
|
||||||
@ -38,7 +51,7 @@ impl GitSync {
|
|||||||
})?;
|
})?;
|
||||||
// Make sure the repo is clean.
|
// Make sure the repo is clean.
|
||||||
if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
|
if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
|
||||||
bail!("working directory must be clean before performing rustc pull");
|
return Err(anyhow::anyhow!("working directory must be clean before performing rustc pull").into());
|
||||||
}
|
}
|
||||||
// Make sure josh is running.
|
// Make sure josh is running.
|
||||||
let josh = Self::start_josh()?;
|
let josh = Self::start_josh()?;
|
||||||
@ -47,7 +60,7 @@ impl GitSync {
|
|||||||
|
|
||||||
let previous_base_commit = sh.read_file("rust-version")?.trim().to_string();
|
let previous_base_commit = sh.read_file("rust-version")?.trim().to_string();
|
||||||
if previous_base_commit == commit {
|
if previous_base_commit == commit {
|
||||||
return Err(anyhow::anyhow!("No changes since last pull"));
|
return Err(RustcPullError::NothingToPull);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update rust-version file. As a separate commit, since making it part of
|
// Update rust-version file. As a separate commit, since making it part of
|
||||||
@ -94,12 +107,13 @@ impl GitSync {
|
|||||||
cmd!(sh, "git reset --hard HEAD^")
|
cmd!(sh, "git reset --hard HEAD^")
|
||||||
.run()
|
.run()
|
||||||
.expect("FAILED to clean up after creating the preparation commit");
|
.expect("FAILED to clean up after creating the preparation commit");
|
||||||
return Err(anyhow::anyhow!("No merge was performed, nothing to pull. Rolled back the preparation commit."));
|
eprintln!("No merge was performed, no changes to pull were found. Rolled back the preparation commit.");
|
||||||
|
return Err(RustcPullError::NothingToPull);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the number of roots did not increase.
|
// Check that the number of roots did not increase.
|
||||||
if num_roots()? != num_roots_before {
|
if num_roots()? != num_roots_before {
|
||||||
bail!("Josh created a new root commit. This is probably not the history you want.");
|
return Err(anyhow::anyhow!("Josh created a new root commit. This is probably not the history you want.").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(josh);
|
drop(josh);
|
||||||
|
@ -1 +1 @@
|
|||||||
66d6064f9eb888018775e08f84747ee6f39ba28e
|
124cc92199ffa924f6b4c7cc819a85b65e0c3984
|
||||||
|
@ -82,7 +82,7 @@ Rust, as well as publications about Rust.
|
|||||||
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](https://amitlevy.com/papers/tock-plos2015.pdf)
|
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](https://amitlevy.com/papers/tock-plos2015.pdf)
|
||||||
* [You can't spell trust without Rust](https://faultlore.com/blah/papers/thesis.pdf). Aria Beingessner's master's thesis.
|
* [You can't spell trust without Rust](https://faultlore.com/blah/papers/thesis.pdf). Aria Beingessner's master's thesis.
|
||||||
* [Rust-Bio: a fast and safe bioinformatics library](https://rust-bio.github.io/). Johannes Köster
|
* [Rust-Bio: a fast and safe bioinformatics library](https://rust-bio.github.io/). Johannes Köster
|
||||||
* [Safe, Correct, and Fast Low-Level Networking](https://octarineparrot.com/assets/msci_paper.pdf). Robert Clipsham's master's thesis.
|
* [Safe, Correct, and Fast Low-Level Networking](https://csperkins.org/research/thesis-msci-clipsham.pdf). Robert Clipsham's master's thesis.
|
||||||
* [Formalizing Rust traits](https://open.library.ubc.ca/cIRcle/collections/ubctheses/24/items/1.0220521). Jonatan Milewski's master's thesis.
|
* [Formalizing Rust traits](https://open.library.ubc.ca/cIRcle/collections/ubctheses/24/items/1.0220521). Jonatan Milewski's master's thesis.
|
||||||
* [Rust as a Language for High Performance GC Implementation](https://dl.acm.org/doi/pdf/10.1145/3241624.2926707)
|
* [Rust as a Language for High Performance GC Implementation](https://dl.acm.org/doi/pdf/10.1145/3241624.2926707)
|
||||||
* [Simple Verification of Rust Programs via Functional Purification](https://github.com/Kha/electrolysis). Sebastian Ullrich's master's thesis.
|
* [Simple Verification of Rust Programs via Functional Purification](https://github.com/Kha/electrolysis). Sebastian Ullrich's master's thesis.
|
||||||
|
@ -135,24 +135,24 @@ and follow the same instructions as above.
|
|||||||
### Emacs
|
### Emacs
|
||||||
|
|
||||||
Emacs provides support for rust-analyzer with project-local configuration
|
Emacs provides support for rust-analyzer with project-local configuration
|
||||||
through [Eglot](https://www.gnu.org/software/emacs/manual/html_node/eglot/).
|
through [Eglot](https://www.gnu.org/software/emacs/manual/html_node/eglot/).
|
||||||
Steps for setting up Eglot with rust-analyzer can be [found
|
Steps for setting up Eglot with rust-analyzer can be [found
|
||||||
here](https://rust-analyzer.github.io/manual.html#eglot).
|
here](https://rust-analyzer.github.io/manual.html#eglot).
|
||||||
Having set up Emacs & Eglot for Rust development in general, you can run
|
Having set up Emacs & Eglot for Rust development in general, you can run
|
||||||
`./x setup editor` and select `emacs`, which will prompt you to create
|
`./x setup editor` and select `emacs`, which will prompt you to create
|
||||||
`.dir-locals.el` with the recommended configuration for Eglot.
|
`.dir-locals.el` with the recommended configuration for Eglot.
|
||||||
The recommended settings live at [`src/etc/rust_analyzer_eglot.el`].
|
The recommended settings live at [`src/etc/rust_analyzer_eglot.el`].
|
||||||
For more information on project-specific Eglot configuration, consult [the
|
For more information on project-specific Eglot configuration, consult [the
|
||||||
manual](https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dspecific-configuration.html).
|
manual](https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dspecific-configuration.html).
|
||||||
|
|
||||||
### Helix
|
### Helix
|
||||||
|
|
||||||
Helix comes with built-in LSP and rust-analyzer support.
|
Helix comes with built-in LSP and rust-analyzer support.
|
||||||
It can be configured through `languages.toml`, as described
|
It can be configured through `languages.toml`, as described
|
||||||
[here](https://docs.helix-editor.com/languages.html).
|
[here](https://docs.helix-editor.com/languages.html).
|
||||||
You can run `./x setup editor` and select `helix`, which will prompt you to
|
You can run `./x setup editor` and select `helix`, which will prompt you to
|
||||||
create `languages.toml` with the recommended configuration for Helix. The
|
create `languages.toml` with the recommended configuration for Helix. The
|
||||||
recommended settings live at [`src/etc/rust_analyzer_helix.toml`].
|
recommended settings live at [`src/etc/rust_analyzer_helix.toml`].
|
||||||
|
|
||||||
## Check, check, and check again
|
## Check, check, and check again
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ example, running `tidy` and `linkchecker` is useful when editing Markdown files,
|
|||||||
whereas UI tests are much less likely to be helpful. While `x suggest` is a
|
whereas UI tests are much less likely to be helpful. While `x suggest` is a
|
||||||
useful tool, it does not guarantee perfect coverage (just as PR CI isn't a
|
useful tool, it does not guarantee perfect coverage (just as PR CI isn't a
|
||||||
substitute for bors). See the [dedicated chapter](../tests/suggest-tests.md) for
|
substitute for bors). See the [dedicated chapter](../tests/suggest-tests.md) for
|
||||||
more information and contribution instructions.
|
more information and contribution instructions.
|
||||||
|
|
||||||
Please note that `x suggest` is in a beta state currently and the tests that it
|
Please note that `x suggest` is in a beta state currently and the tests that it
|
||||||
will suggest are limited.
|
will suggest are limited.
|
||||||
@ -332,28 +332,21 @@ git worktree add -b my-feature ../rust2 master
|
|||||||
You can then use that rust2 folder as a separate workspace for modifying and
|
You can then use that rust2 folder as a separate workspace for modifying and
|
||||||
building `rustc`!
|
building `rustc`!
|
||||||
|
|
||||||
## Using nix-shell
|
## Working with nix
|
||||||
|
|
||||||
If you're using nix, you can use the following nix-shell to work on Rust:
|
Several nix configurations are defined in `src/tools/nix-dev-shell`.
|
||||||
|
|
||||||
```nix
|
If you're using direnv, you can create a symbol link to `src/tools/nix-dev-shell/envrc-flake` or `src/tools/nix-dev-shell/envrc-shell`
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
|
||||||
pkgs.mkShell {
|
```bash
|
||||||
name = "rustc";
|
ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc # Use flake
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
binutils cmake ninja pkg-config python3 git curl cacert patchelf nix
|
|
||||||
];
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
openssl glibc.out glibc.static
|
|
||||||
];
|
|
||||||
# Avoid creating text files for ICEs.
|
|
||||||
RUSTC_ICE = "0";
|
|
||||||
# Provide `libstdc++.so.6` for the self-contained lld.
|
|
||||||
LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [
|
|
||||||
stdenv.cc.cc.lib
|
|
||||||
]}";
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell
|
||||||
|
```
|
||||||
|
|
||||||
|
### Note
|
||||||
|
|
||||||
Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
||||||
**`patch-binaries-for-nix = true` in `config.toml`**. Bootstrap tries to detect
|
**`patch-binaries-for-nix = true` in `config.toml`**. Bootstrap tries to detect
|
||||||
|
@ -601,8 +601,8 @@ The trait implementation allows you to check certain syntactic constructs
|
|||||||
as the linter walks the AST. You can then choose to emit lints in a
|
as the linter walks the AST. You can then choose to emit lints in a
|
||||||
very similar way to compile errors.
|
very similar way to compile errors.
|
||||||
|
|
||||||
You also declare the metadata of a particular lint via the `declare_lint!`
|
You also declare the metadata of a particular lint via the [`declare_lint!`]
|
||||||
macro. [This macro](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/macro.declare_lint.html) includes the name, the default level, a short description, and some
|
macro. This macro includes the name, the default level, a short description, and some
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
Note that the lint and the lint pass must be registered with the compiler.
|
Note that the lint and the lint pass must be registered with the compiler.
|
||||||
@ -671,6 +671,8 @@ example-use-loop = denote infinite loops with `loop {"{"} ... {"}"}`
|
|||||||
.suggestion = use `loop`
|
.suggestion = use `loop`
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/macro.declare_lint.html
|
||||||
|
|
||||||
### Edition-gated lints
|
### Edition-gated lints
|
||||||
|
|
||||||
Sometimes we want to change the behavior of a lint in a new edition. To do this,
|
Sometimes we want to change the behavior of a lint in a new edition. To do this,
|
||||||
|
@ -101,7 +101,6 @@ it's easy to pick up work without a large time commitment:
|
|||||||
- [Rustdoc Askama Migration](https://github.com/rust-lang/rust/issues/108868)
|
- [Rustdoc Askama Migration](https://github.com/rust-lang/rust/issues/108868)
|
||||||
- [Diagnostic Translation](https://github.com/rust-lang/rust/issues/100717)
|
- [Diagnostic Translation](https://github.com/rust-lang/rust/issues/100717)
|
||||||
- [Move UI tests to subdirectories](https://github.com/rust-lang/rust/issues/73494)
|
- [Move UI tests to subdirectories](https://github.com/rust-lang/rust/issues/73494)
|
||||||
- [Port run-make tests from Make to Rust](https://github.com/rust-lang/rust/issues/121876)
|
|
||||||
|
|
||||||
If you find more recurring work, please feel free to add it here!
|
If you find more recurring work, please feel free to add it here!
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ Creating an env from an arbitrary set of where clauses is usually unnecessary an
|
|||||||
|
|
||||||
Creating an empty environment via `ParamEnv::empty` is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the `ParamEnv` there should be constructed via `ParamEnv::reveal_all` instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using `ParamEnv::reveal_all`.
|
Creating an empty environment via `ParamEnv::empty` is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the `ParamEnv` there should be constructed via `ParamEnv::reveal_all` instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using `ParamEnv::reveal_all`.
|
||||||
|
|
||||||
An additional piece of complexity here is specifying the [`Reveal`][reveal] (see linked docs for explanation of what reveal does) used for the `ParamEnv`. When constructing a param env using the `param_env` query it will have `Reveal::UserFacing`, if `Reveal::All` is desired then the [`tcx.param_env_reveal_all_normalized`][env_reveal_all_normalized] query can be used instead.
|
An additional piece of complexity here is specifying the `Reveal` (see linked docs for explanation of what reveal does) used for the `ParamEnv`. When constructing a param env using the `param_env` query it will have `Reveal::UserFacing`, if `Reveal::All` is desired then the [`tcx.param_env_reveal_all_normalized`][env_reveal_all_normalized] query can be used instead.
|
||||||
|
|
||||||
The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_reveal_all] which converts an existing `ParamEnv` into one with `Reveal::All` specified. Where possible the previously mentioned query should be preferred as it is more efficient.
|
The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_reveal_all] which converts an existing `ParamEnv` into one with `Reveal::All` specified. Where possible the previously mentioned query should be preferred as it is more efficient.
|
||||||
|
|
||||||
@ -38,7 +38,6 @@ The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_r
|
|||||||
[with_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.with_reveal_all_normalized
|
[with_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.with_reveal_all_normalized
|
||||||
[env_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.reveal_all
|
[env_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.reveal_all
|
||||||
[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty
|
[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty
|
||||||
[reveal]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/enum.Reveal.html
|
|
||||||
[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
|
[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
|
||||||
[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env
|
[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env
|
||||||
[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
|
[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system.
|
The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system.
|
||||||
|
|
||||||
The information represented by `ParamEnv` is a list of in-scope where-clauses, and a [`Reveal`][reveal] (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds.
|
The information represented by `ParamEnv` is a list of in-scope where-clauses, and a `Reveal` (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds.
|
||||||
|
|
||||||
A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses.
|
A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses.
|
||||||
|
|
||||||
@ -57,4 +57,3 @@ It's very important to use the correct `ParamEnv` when interacting with the type
|
|||||||
[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
|
[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
|
||||||
[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
|
[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
|
||||||
[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env
|
[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env
|
||||||
[reveal]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/enum.Reveal.html
|
|
@ -46,8 +46,8 @@ For space savings, it's also written without newlines or spaces.
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
[`src/librustdoc/html/static/js/externs.js`]
|
[`src/librustdoc/html/static/js/rustdoc.d.ts`]
|
||||||
defines an actual schema in a Closure `@typedef`.
|
defines an actual schema in a TypeScript `type`.
|
||||||
|
|
||||||
| Key | Name | Description |
|
| Key | Name | Description |
|
||||||
| --- | -------------------- | ------------ |
|
| --- | -------------------- | ------------ |
|
||||||
@ -68,7 +68,7 @@ with a free function called `function_name` and a struct called `Data`,
|
|||||||
with the type signature `Data, i32 -> str`,
|
with the type signature `Data, i32 -> str`,
|
||||||
and an alias, `get_name`, that equivalently refers to `function_name`.
|
and an alias, `get_name`, that equivalently refers to `function_name`.
|
||||||
|
|
||||||
[`src/librustdoc/html/static/js/externs.js`]: https://github.com/rust-lang/rust/blob/79b710c13968a1a48d94431d024d2b1677940866/src/librustdoc/html/static/js/externs.js#L204-L258
|
[`src/librustdoc/html/static/js/rustdoc.d.ts`]: https://github.com/rust-lang/rust/blob/2f92f050e83bf3312ce4ba73c31fe843ad3cbc60/src/librustdoc/html/static/js/rustdoc.d.ts#L344-L390
|
||||||
|
|
||||||
The search index needs to fit the needs of the `rustdoc` compiler,
|
The search index needs to fit the needs of the `rustdoc` compiler,
|
||||||
the `search.js` frontend,
|
the `search.js` frontend,
|
||||||
@ -469,7 +469,7 @@ want the libs team to be able to add new items without causing unrelated
|
|||||||
tests to fail, but standalone tests will use it more often.
|
tests to fail, but standalone tests will use it more often.
|
||||||
|
|
||||||
The `ResultsTable` and `ParsedQuery` types are specified in
|
The `ResultsTable` and `ParsedQuery` types are specified in
|
||||||
[`externs.js`](https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/js/externs.js).
|
[`rustdoc.d.ts`](https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/js/rustdoc.d.ts).
|
||||||
|
|
||||||
For example, imagine we needed to fix a bug where a function named
|
For example, imagine we needed to fix a bug where a function named
|
||||||
`constructor` couldn't be found. To do this, write two files:
|
`constructor` couldn't be found. To do this, write two files:
|
||||||
|
@ -322,7 +322,7 @@ Our CI workflow uses various caching mechanisms, mainly for two things:
|
|||||||
### Docker images caching
|
### Docker images caching
|
||||||
|
|
||||||
The Docker images we use to run most of the Linux-based builders take a *long*
|
The Docker images we use to run most of the Linux-based builders take a *long*
|
||||||
time to fully build. To speed up the build, we cache it using [Docker registry
|
time to fully build. To speed up the build, we cache them using [Docker registry
|
||||||
caching], with the intermediate artifacts being stored on [ghcr.io]. We also
|
caching], with the intermediate artifacts being stored on [ghcr.io]. We also
|
||||||
push the built Docker images to ghcr, so that they can be reused by other tools
|
push the built Docker images to ghcr, so that they can be reused by other tools
|
||||||
(rustup) or by developers running the Docker build locally (to speed up their
|
(rustup) or by developers running the Docker build locally (to speed up their
|
||||||
@ -334,6 +334,13 @@ override the cache for the others. Instead, we store the images under different
|
|||||||
tags, identifying them with a custom hash made from the contents of all the
|
tags, identifying them with a custom hash made from the contents of all the
|
||||||
Dockerfiles and related scripts.
|
Dockerfiles and related scripts.
|
||||||
|
|
||||||
|
The CI calculates a hash key, so that the cache of a Docker image is
|
||||||
|
invalidated if one of the following changes:
|
||||||
|
|
||||||
|
- Dockerfile
|
||||||
|
- Files copied into the Docker image in the Dockerfile
|
||||||
|
- The architecture of the GitHub runner (x86 or ARM)
|
||||||
|
|
||||||
[ghcr.io]: https://github.com/rust-lang-ci/rust/pkgs/container/rust-ci
|
[ghcr.io]: https://github.com/rust-lang-ci/rust/pkgs/container/rust-ci
|
||||||
[Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/
|
[Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/
|
||||||
|
|
||||||
@ -341,9 +348,18 @@ Dockerfiles and related scripts.
|
|||||||
|
|
||||||
We build some C/C++ stuff in various CI jobs, and we rely on [sccache] to cache
|
We build some C/C++ stuff in various CI jobs, and we rely on [sccache] to cache
|
||||||
the intermediate LLVM artifacts. Sccache is a distributed ccache developed by
|
the intermediate LLVM artifacts. Sccache is a distributed ccache developed by
|
||||||
Mozilla, which can use an object storage bucket as the storage backend. In our
|
Mozilla, which can use an object storage bucket as the storage backend.
|
||||||
case, the artefacts are uploaded to an S3 bucket that we control
|
|
||||||
(`rust-lang-ci-sccache2`).
|
With sccache there's no need to calculate the hash key ourselves. Sccache
|
||||||
|
invalidates the cache automatically when it detects changes to relevant inputs,
|
||||||
|
such as the source code, the version of the compiler, and important environment
|
||||||
|
variables.
|
||||||
|
So we just pass the sccache wrapper on top of cargo and sccache does the rest.
|
||||||
|
|
||||||
|
We store the persistent artifacts on the S3 bucket `rust-lang-ci-sccache2`. So
|
||||||
|
when the CI runs, if sccache sees that LLVM is being compiled with the same C/C++
|
||||||
|
compiler and the LLVM source code is the same, sccache retrieves the individual
|
||||||
|
compiled translation units from S3.
|
||||||
|
|
||||||
[sccache]: https://github.com/mozilla/sccache
|
[sccache]: https://github.com/mozilla/sccache
|
||||||
|
|
||||||
|
@ -1,36 +1,44 @@
|
|||||||
# Testing with Docker
|
# Testing with Docker
|
||||||
|
|
||||||
The Rust tree includes [Docker] image definitions for the platforms used on
|
The [`src/ci/docker`] directory includes [Docker] image definitions for Linux-based jobs executed on GitHub Actions (non-Linux jobs run outside Docker). You can run these jobs on your local development machine, which can be
|
||||||
GitHub Actions in [`src/ci/docker`].
|
helpful to test environments different from your local system. You will
|
||||||
The script [`src/ci/docker/run.sh`] is used to build the Docker image, run it,
|
|
||||||
build Rust within the image, and run the tests.
|
|
||||||
|
|
||||||
You can run these images on your local development machine. This can be
|
|
||||||
helpful to test environments different from your local system. First you will
|
|
||||||
need to install Docker on a Linux, Windows, or macOS system (typically Linux
|
need to install Docker on a Linux, Windows, or macOS system (typically Linux
|
||||||
will be much faster than Windows or macOS because the latter use virtual
|
will be much faster than Windows or macOS because the latter use virtual
|
||||||
machines to emulate a Linux environment). To enter interactive mode which will
|
machines to emulate a Linux environment).
|
||||||
start a bash shell in the container, run `src/ci/docker/run.sh --dev <IMAGE>`
|
|
||||||
where `<IMAGE>` is one of the directory names in `src/ci/docker` (for example
|
|
||||||
`x86_64-gnu` is a fairly standard Ubuntu environment).
|
|
||||||
|
|
||||||
The docker script will mount your local Rust source tree in read-only mode,
|
Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper Python script that tries to replicate what happens on CI as closely as possible:
|
||||||
and an `obj` directory in read-write mode. All of the compiler artifacts will
|
|
||||||
be stored in the `obj` directory. The shell will start out in the `obj`
|
|
||||||
directory. From there, you can run `../src/ci/run.sh` which will run the build
|
|
||||||
as defined by the image.
|
|
||||||
|
|
||||||
Alternatively, you can run individual commands to do specific tasks. For
|
```bash
|
||||||
example, you can run `../x test tests/ui` to just run UI tests.
|
python3 src/ci/github-actions/ci.py run-local <job-name>
|
||||||
Note that there is some configuration in the [`src/ci/run.sh`] script that you
|
# For example:
|
||||||
may need to recreate. Particularly, set `submodules = false` in your
|
python3 src/ci/github-actions/ci.py run-local dist-x86_64-linux-alt
|
||||||
`config.toml` so that it doesn't attempt to modify the read-only directory.
|
```
|
||||||
|
|
||||||
Some additional notes about using the Docker images:
|
If the above script does not work for you, you would like to have more control of the Docker image execution, or you want to understand what exactly happens during Docker job execution, then continue reading below.
|
||||||
|
|
||||||
|
## The `run.sh` script
|
||||||
|
The [`src/ci/docker/run.sh`] script is used to build a specific Docker image, run it,
|
||||||
|
build Rust within the image, and either run tests or prepare a set of archives designed for distribution. The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. All the compiler artifacts will be stored in the `obj` directory. The shell will start out in the `obj`directory. From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image.
|
||||||
|
|
||||||
|
You can run `src/ci/docker/run.sh <image-name>` directly. A few important notes regarding the `run.sh` script:
|
||||||
|
- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `submodules = true` in your `config.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though).
|
||||||
|
- `<image-name>` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally).
|
||||||
|
- If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable.
|
||||||
|
- If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable.
|
||||||
- Some of the std tests require IPv6 support. Docker on Linux seems to have it
|
- Some of the std tests require IPv6 support. Docker on Linux seems to have it
|
||||||
disabled by default. Run the commands in [`enable-docker-ipv6.sh`] to enable
|
disabled by default. Run the commands in [`enable-docker-ipv6.sh`] to enable
|
||||||
IPv6 before creating the container. This only needs to be done once.
|
IPv6 before creating the container. This only needs to be done once.
|
||||||
|
|
||||||
|
### Interactive mode
|
||||||
|
|
||||||
|
Sometimes, it can be useful to build a specific Docker image, and then run custom commands inside it, so that you can experiment with how the given system behaves. You can do that using an interactive mode, which will
|
||||||
|
start a bash shell in the container, using `src/ci/docker/run.sh --dev <image-name>`.
|
||||||
|
|
||||||
|
When inside the Docker container, you can run individual commands to do specific tasks. For
|
||||||
|
example, you can run `../x test tests/ui` to just run UI tests.
|
||||||
|
|
||||||
|
Some additional notes about using the interactive mode:
|
||||||
|
|
||||||
- The container will be deleted automatically when you exit the shell, however
|
- The container will be deleted automatically when you exit the shell, however
|
||||||
the build artifacts persist in the `obj` directory. If you are switching
|
the build artifacts persist in the `obj` directory. If you are switching
|
||||||
between different Docker images, the artifacts from previous environments
|
between different Docker images, the artifacts from previous environments
|
||||||
@ -45,15 +53,6 @@ Some additional notes about using the Docker images:
|
|||||||
containers. With the container name, run `docker exec -it <CONTAINER>
|
containers. With the container name, run `docker exec -it <CONTAINER>
|
||||||
/bin/bash` where `<CONTAINER>` is the container name like `4ba195e95cef`.
|
/bin/bash` where `<CONTAINER>` is the container name like `4ba195e95cef`.
|
||||||
|
|
||||||
The approach described above is a relatively low-level interface for running the Docker images
|
|
||||||
directly. If you want to run a full CI Linux job locally with Docker, in a way that is as close to CI as possible, you can use the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 src/ci/github-actions/ci.py run-local <job-name>
|
|
||||||
# For example:
|
|
||||||
python3 src/ci/github-actions/ci.py run-local dist-x86_64-linux-alt
|
|
||||||
```
|
|
||||||
|
|
||||||
[Docker]: https://www.docker.com/
|
[Docker]: https://www.docker.com/
|
||||||
[`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker
|
[`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker
|
||||||
[`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh
|
[`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh
|
||||||
|
@ -40,7 +40,7 @@ requirements of impls and functions as explicit predicates.
|
|||||||
### using implicit implied bounds as assumptions
|
### using implicit implied bounds as assumptions
|
||||||
|
|
||||||
These bounds are not added to the `ParamEnv` of the affected item itself. For lexical
|
These bounds are not added to the `ParamEnv` of the affected item itself. For lexical
|
||||||
region resolution they are added using [`fn OutlivesEnvironment::new`].
|
region resolution they are added using [`fn OutlivesEnvironment::from_normalized_bounds`].
|
||||||
Similarly, during MIR borrowck we add them using
|
Similarly, during MIR borrowck we add them using
|
||||||
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`].
|
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`].
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ The assumed outlives constraints for implicit bounds are computed using the
|
|||||||
MIR borrowck adds the outlives constraints for both the normalized and unnormalized types,
|
MIR borrowck adds the outlives constraints for both the normalized and unnormalized types,
|
||||||
lexical region resolution [only uses the unnormalized types][notnorm].
|
lexical region resolution [only uses the unnormalized types][notnorm].
|
||||||
|
|
||||||
[`fn OutlivesEnvironment::new`]: TODO
|
[`fn OutlivesEnvironment::from_normalized_bounds`]: https://github.com/rust-lang/rust/blob/8239a37f9c0951a037cfc51763ea52a20e71e6bd/compiler/rustc_infer/src/infer/outlives/env.rs#L50-L55
|
||||||
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L316
|
[`fn UniversalRegionRelationsBuilder::add_implied_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L316
|
||||||
[mir]: https://github.com/rust-lang/rust/blob/91cae1dcdcf1a31bd8a92e4a63793d65cfe289bb/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L258-L332
|
[mir]: https://github.com/rust-lang/rust/blob/91cae1dcdcf1a31bd8a92e4a63793d65cfe289bb/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L258-L332
|
||||||
[`fn assumed_wf_types`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_ty_utils/src/implied_bounds.rs#L21
|
[`fn assumed_wf_types`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_ty_utils/src/implied_bounds.rs#L21
|
||||||
|
@ -311,12 +311,12 @@ target | std | host | notes
|
|||||||
[`i386-apple-ios`](platform-support/apple-ios.md) | ✓ | | 32-bit x86 iOS (Penryn) [^x86_32-floats-return-ABI]
|
[`i386-apple-ios`](platform-support/apple-ios.md) | ✓ | | 32-bit x86 iOS (Penryn) [^x86_32-floats-return-ABI]
|
||||||
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI]
|
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI]
|
||||||
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86 (original Pentium) [^x86_32-floats-x87]
|
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86 (original Pentium) [^x86_32-floats-x87]
|
||||||
|
[`i586-unknown-redox`](platform-support/redox.md) | ✓ | | 32-bit x86 Redox OS (PentiumPro) [^x86_32-floats-x87]
|
||||||
[`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI]
|
[`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI]
|
||||||
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI]
|
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI]
|
||||||
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI]
|
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI]
|
||||||
[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI]
|
[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI]
|
||||||
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD (Pentium 4) [^x86_32-floats-return-ABI]
|
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD (Pentium 4) [^x86_32-floats-return-ABI]
|
||||||
[`i686-unknown-redox`](platform-support/redox.md) | ✓ | | i686 Redox OS (PentiumPro) [^x86_32-floats-x87]
|
|
||||||
`i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI]
|
`i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI]
|
||||||
[`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ | | [^x86_32-floats-return-ABI]
|
[`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ | | [^x86_32-floats-return-ABI]
|
||||||
[`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
|
[`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
|
||||||
|
@ -9,7 +9,7 @@ Target triplets available so far:
|
|||||||
|
|
||||||
- `x86_64-unknown-redox` (tier 2)
|
- `x86_64-unknown-redox` (tier 2)
|
||||||
- `aarch64-unknown-redox` (tier 3)
|
- `aarch64-unknown-redox` (tier 3)
|
||||||
- `i686-unknown-redox` (tier 3)
|
- `i586-unknown-redox` (tier 3)
|
||||||
|
|
||||||
## Target maintainers
|
## Target maintainers
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ target = [
|
|||||||
"<HOST_TARGET>",
|
"<HOST_TARGET>",
|
||||||
"x86_64-unknown-redox",
|
"x86_64-unknown-redox",
|
||||||
"aarch64-unknown-redox",
|
"aarch64-unknown-redox",
|
||||||
"i686-unknown-redox",
|
"i586-unknown-redox",
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ pub(crate) fn render_example_with_highlighting(
|
|||||||
extra_classes: &[String],
|
extra_classes: &[String],
|
||||||
) {
|
) {
|
||||||
write_header(out, "rust-example-rendered", None, tooltip, extra_classes);
|
write_header(out, "rust-example-rendered", None, tooltip, extra_classes);
|
||||||
write_code(out, src, None, None);
|
write_code(out, src, None, None, None);
|
||||||
write_footer(out, playground_button);
|
write_footer(out, playground_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +150,7 @@ struct TokenHandler<'a, 'tcx, F: Write> {
|
|||||||
/// used to generate links.
|
/// used to generate links.
|
||||||
pending_elems: Vec<(&'a str, Option<Class>)>,
|
pending_elems: Vec<(&'a str, Option<Class>)>,
|
||||||
href_context: Option<HrefContext<'a, 'tcx>>,
|
href_context: Option<HrefContext<'a, 'tcx>>,
|
||||||
|
write_line_number: fn(&mut F, u32, &'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Write> TokenHandler<'_, '_, F> {
|
impl<F: Write> TokenHandler<'_, '_, F> {
|
||||||
@ -182,7 +183,14 @@ impl<F: Write> TokenHandler<'_, '_, F> {
|
|||||||
&& can_merge(current_class, Some(*parent_class), "")
|
&& can_merge(current_class, Some(*parent_class), "")
|
||||||
{
|
{
|
||||||
for (text, class) in self.pending_elems.iter() {
|
for (text, class) in self.pending_elems.iter() {
|
||||||
string(self.out, EscapeBodyText(text), *class, &self.href_context, false);
|
string(
|
||||||
|
self.out,
|
||||||
|
EscapeBodyText(text),
|
||||||
|
*class,
|
||||||
|
&self.href_context,
|
||||||
|
false,
|
||||||
|
self.write_line_number,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We only want to "open" the tag ourselves if we have more than one pending and if the
|
// We only want to "open" the tag ourselves if we have more than one pending and if the
|
||||||
@ -204,6 +212,7 @@ impl<F: Write> TokenHandler<'_, '_, F> {
|
|||||||
*class,
|
*class,
|
||||||
&self.href_context,
|
&self.href_context,
|
||||||
close_tag.is_none(),
|
close_tag.is_none(),
|
||||||
|
self.write_line_number,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(close_tag) = close_tag {
|
if let Some(close_tag) = close_tag {
|
||||||
@ -213,6 +222,11 @@ impl<F: Write> TokenHandler<'_, '_, F> {
|
|||||||
self.pending_elems.clear();
|
self.pending_elems.clear();
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_line_number(&mut self, line: u32, extra: &'static str) {
|
||||||
|
(self.write_line_number)(&mut self.out, line, extra);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Write> Drop for TokenHandler<'_, '_, F> {
|
impl<F: Write> Drop for TokenHandler<'_, '_, F> {
|
||||||
@ -226,6 +240,43 @@ impl<F: Write> Drop for TokenHandler<'_, '_, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_scraped_line_number(out: &mut impl Write, line: u32, extra: &'static str) {
|
||||||
|
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
|
||||||
|
// Do not show "1 2 3 4 5 ..." in web search results.
|
||||||
|
write!(out, "{extra}<span data-nosnippet>{line}</span>",).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_line_number(out: &mut impl Write, line: u32, extra: &'static str) {
|
||||||
|
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
|
||||||
|
// Do not show "1 2 3 4 5 ..." in web search results.
|
||||||
|
write!(out, "{extra}<a href=#{line} id={line} data-nosnippet>{line}</a>",).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_line_number(out: &mut impl Write, _: u32, extra: &'static str) {
|
||||||
|
out.write_str(extra).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(super) struct LineInfo {
|
||||||
|
pub(super) start_line: u32,
|
||||||
|
max_lines: u32,
|
||||||
|
pub(super) is_scraped_example: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineInfo {
|
||||||
|
pub(super) fn new(max_lines: u32) -> Self {
|
||||||
|
Self { start_line: 1, max_lines: max_lines + 1, is_scraped_example: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn new_scraped(max_lines: u32, start_line: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
start_line: start_line + 1,
|
||||||
|
max_lines: max_lines + start_line + 1,
|
||||||
|
is_scraped_example: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert the given `src` source code into HTML by adding classes for highlighting.
|
/// Convert the given `src` source code into HTML by adding classes for highlighting.
|
||||||
///
|
///
|
||||||
/// This code is used to render code blocks (in the documentation) as well as the source code pages.
|
/// This code is used to render code blocks (in the documentation) as well as the source code pages.
|
||||||
@ -242,6 +293,7 @@ pub(super) fn write_code(
|
|||||||
src: &str,
|
src: &str,
|
||||||
href_context: Option<HrefContext<'_, '_>>,
|
href_context: Option<HrefContext<'_, '_>>,
|
||||||
decoration_info: Option<&DecorationInfo>,
|
decoration_info: Option<&DecorationInfo>,
|
||||||
|
line_info: Option<LineInfo>,
|
||||||
) {
|
) {
|
||||||
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
||||||
let src = src.replace("\r\n", "\n");
|
let src = src.replace("\r\n", "\n");
|
||||||
@ -252,6 +304,23 @@ pub(super) fn write_code(
|
|||||||
current_class: None,
|
current_class: None,
|
||||||
pending_elems: Vec::new(),
|
pending_elems: Vec::new(),
|
||||||
href_context,
|
href_context,
|
||||||
|
write_line_number: match line_info {
|
||||||
|
Some(line_info) => {
|
||||||
|
if line_info.is_scraped_example {
|
||||||
|
write_scraped_line_number
|
||||||
|
} else {
|
||||||
|
write_line_number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => empty_line_number,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let (mut line, max_lines) = if let Some(line_info) = line_info {
|
||||||
|
token_handler.write_line_number(line_info.start_line, "");
|
||||||
|
(line_info.start_line, line_info.max_lines)
|
||||||
|
} else {
|
||||||
|
(0, u32::MAX)
|
||||||
};
|
};
|
||||||
|
|
||||||
Classifier::new(
|
Classifier::new(
|
||||||
@ -282,7 +351,14 @@ pub(super) fn write_code(
|
|||||||
if need_current_class_update {
|
if need_current_class_update {
|
||||||
token_handler.current_class = class.map(Class::dummy);
|
token_handler.current_class = class.map(Class::dummy);
|
||||||
}
|
}
|
||||||
token_handler.pending_elems.push((text, class));
|
if text == "\n" {
|
||||||
|
line += 1;
|
||||||
|
if line < max_lines {
|
||||||
|
token_handler.pending_elems.push((text, Some(Class::Backline(line))));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
token_handler.pending_elems.push((text, class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Highlight::EnterSpan { class } => {
|
Highlight::EnterSpan { class } => {
|
||||||
let mut should_add = true;
|
let mut should_add = true;
|
||||||
@ -348,6 +424,7 @@ enum Class {
|
|||||||
PreludeVal(Span),
|
PreludeVal(Span),
|
||||||
QuestionMark,
|
QuestionMark,
|
||||||
Decoration(&'static str),
|
Decoration(&'static str),
|
||||||
|
Backline(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
@ -396,6 +473,7 @@ impl Class {
|
|||||||
Class::PreludeVal(_) => "prelude-val",
|
Class::PreludeVal(_) => "prelude-val",
|
||||||
Class::QuestionMark => "question-mark",
|
Class::QuestionMark => "question-mark",
|
||||||
Class::Decoration(kind) => kind,
|
Class::Decoration(kind) => kind,
|
||||||
|
Class::Backline(_) => "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +497,8 @@ impl Class {
|
|||||||
| Self::Bool
|
| Self::Bool
|
||||||
| Self::Lifetime
|
| Self::Lifetime
|
||||||
| Self::QuestionMark
|
| Self::QuestionMark
|
||||||
| Self::Decoration(_) => None,
|
| Self::Decoration(_)
|
||||||
|
| Self::Backline(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -694,8 +773,13 @@ impl<'src> Classifier<'src> {
|
|||||||
) {
|
) {
|
||||||
let lookahead = self.peek();
|
let lookahead = self.peek();
|
||||||
let no_highlight = |sink: &mut dyn FnMut(_)| sink(Highlight::Token { text, class: None });
|
let no_highlight = |sink: &mut dyn FnMut(_)| sink(Highlight::Token { text, class: None });
|
||||||
|
let whitespace = |sink: &mut dyn FnMut(_)| {
|
||||||
|
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
|
||||||
|
sink(Highlight::Token { text: part, class: None });
|
||||||
|
}
|
||||||
|
};
|
||||||
let class = match token {
|
let class = match token {
|
||||||
TokenKind::Whitespace => return no_highlight(sink),
|
TokenKind::Whitespace => return whitespace(sink),
|
||||||
TokenKind::LineComment { doc_style } | TokenKind::BlockComment { doc_style, .. } => {
|
TokenKind::LineComment { doc_style } | TokenKind::BlockComment { doc_style, .. } => {
|
||||||
if doc_style.is_some() {
|
if doc_style.is_some() {
|
||||||
Class::DocComment
|
Class::DocComment
|
||||||
@ -716,7 +800,7 @@ impl<'src> Classifier<'src> {
|
|||||||
// or a reference or pointer type. Unless, of course, it looks like
|
// or a reference or pointer type. Unless, of course, it looks like
|
||||||
// a logical and or a multiplication operator: `&&` or `* `.
|
// a logical and or a multiplication operator: `&&` or `* `.
|
||||||
TokenKind::Star => match self.tokens.peek() {
|
TokenKind::Star => match self.tokens.peek() {
|
||||||
Some((TokenKind::Whitespace, _)) => return no_highlight(sink),
|
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
|
||||||
Some((TokenKind::Ident, "mut")) => {
|
Some((TokenKind::Ident, "mut")) => {
|
||||||
self.next();
|
self.next();
|
||||||
sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) });
|
sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) });
|
||||||
@ -740,7 +824,7 @@ impl<'src> Classifier<'src> {
|
|||||||
sink(Highlight::Token { text: "&=", class: None });
|
sink(Highlight::Token { text: "&=", class: None });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Some((TokenKind::Whitespace, _)) => return no_highlight(sink),
|
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
|
||||||
Some((TokenKind::Ident, "mut")) => {
|
Some((TokenKind::Ident, "mut")) => {
|
||||||
self.next();
|
self.next();
|
||||||
sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) });
|
sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) });
|
||||||
@ -887,7 +971,9 @@ impl<'src> Classifier<'src> {
|
|||||||
};
|
};
|
||||||
// Anything that didn't return above is the simple case where we the
|
// Anything that didn't return above is the simple case where we the
|
||||||
// class just spans a single token, so we can use the `string` method.
|
// class just spans a single token, so we can use the `string` method.
|
||||||
sink(Highlight::Token { text, class: Some(class) });
|
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
|
||||||
|
sink(Highlight::Token { text: part, class: Some(class) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek(&mut self) -> Option<TokenKind> {
|
fn peek(&mut self) -> Option<TokenKind> {
|
||||||
@ -939,14 +1025,18 @@ fn exit_span(out: &mut impl Write, closing_tag: &str) {
|
|||||||
/// Note that if `context` is not `None` and that the given `klass` contains a `Span`, the function
|
/// Note that if `context` is not `None` and that the given `klass` contains a `Span`, the function
|
||||||
/// will then try to find this `span` in the `span_correspondence_map`. If found, it'll then
|
/// will then try to find this `span` in the `span_correspondence_map`. If found, it'll then
|
||||||
/// generate a link for this element (which corresponds to where its definition is located).
|
/// generate a link for this element (which corresponds to where its definition is located).
|
||||||
fn string<T: Display>(
|
fn string<T: Display, W: Write>(
|
||||||
out: &mut impl Write,
|
out: &mut W,
|
||||||
text: T,
|
text: T,
|
||||||
klass: Option<Class>,
|
klass: Option<Class>,
|
||||||
href_context: &Option<HrefContext<'_, '_>>,
|
href_context: &Option<HrefContext<'_, '_>>,
|
||||||
open_tag: bool,
|
open_tag: bool,
|
||||||
|
write_line_number_callback: fn(&mut W, u32, &'static str),
|
||||||
) {
|
) {
|
||||||
if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
|
if let Some(Class::Backline(line)) = klass {
|
||||||
|
write_line_number_callback(out, line, "\n");
|
||||||
|
} else if let Some(closing_tag) =
|
||||||
|
string_without_closing_tag(out, text, klass, href_context, open_tag)
|
||||||
{
|
{
|
||||||
out.write_str(closing_tag).unwrap();
|
out.write_str(closing_tag).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ fn test_html_highlighting() {
|
|||||||
let src = include_str!("fixtures/sample.rs");
|
let src = include_str!("fixtures/sample.rs");
|
||||||
let html = {
|
let html = {
|
||||||
let mut out = Buffer::new();
|
let mut out = Buffer::new();
|
||||||
write_code(&mut out, src, None, None);
|
write_code(&mut out, src, None, None, None);
|
||||||
format!("{STYLE}<pre><code>{}</code></pre>\n", out.into_inner())
|
format!("{STYLE}<pre><code>{}</code></pre>\n", out.into_inner())
|
||||||
};
|
};
|
||||||
expect_file!["fixtures/sample.html"].assert_eq(&html);
|
expect_file!["fixtures/sample.html"].assert_eq(&html);
|
||||||
@ -37,7 +37,7 @@ fn test_dos_backline() {
|
|||||||
println!(\"foo\");\r\n\
|
println!(\"foo\");\r\n\
|
||||||
}\r\n";
|
}\r\n";
|
||||||
let mut html = Buffer::new();
|
let mut html = Buffer::new();
|
||||||
write_code(&mut html, src, None, None);
|
write_code(&mut html, src, None, None, None);
|
||||||
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
|
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ let x = super::b::foo;
|
|||||||
let y = Self::whatever;";
|
let y = Self::whatever;";
|
||||||
|
|
||||||
let mut html = Buffer::new();
|
let mut html = Buffer::new();
|
||||||
write_code(&mut html, src, None, None);
|
write_code(&mut html, src, None, None, None);
|
||||||
expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner());
|
expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ fn test_union_highlighting() {
|
|||||||
create_default_session_globals_then(|| {
|
create_default_session_globals_then(|| {
|
||||||
let src = include_str!("fixtures/union.rs");
|
let src = include_str!("fixtures/union.rs");
|
||||||
let mut html = Buffer::new();
|
let mut html = Buffer::new();
|
||||||
write_code(&mut html, src, None, None);
|
write_code(&mut html, src, None, None, None);
|
||||||
expect_file!["fixtures/union.html"].assert_eq(&html.into_inner());
|
expect_file!["fixtures/union.html"].assert_eq(&html.into_inner());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ let a = 4;";
|
|||||||
decorations.insert("example2", vec![(22, 32)]);
|
decorations.insert("example2", vec![(22, 32)]);
|
||||||
|
|
||||||
let mut html = Buffer::new();
|
let mut html = Buffer::new();
|
||||||
write_code(&mut html, src, None, Some(&DecorationInfo(decorations)));
|
write_code(&mut html, src, None, Some(&DecorationInfo(decorations)), None);
|
||||||
expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner());
|
expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::ops::RangeInclusive;
|
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::{fmt, fs};
|
use std::{fmt, fs};
|
||||||
|
|
||||||
@ -303,16 +302,16 @@ pub(crate) struct ScrapedInfo<'a> {
|
|||||||
#[template(path = "scraped_source.html")]
|
#[template(path = "scraped_source.html")]
|
||||||
struct ScrapedSource<'a, Code: std::fmt::Display> {
|
struct ScrapedSource<'a, Code: std::fmt::Display> {
|
||||||
info: ScrapedInfo<'a>,
|
info: ScrapedInfo<'a>,
|
||||||
lines: RangeInclusive<usize>,
|
|
||||||
code_html: Code,
|
code_html: Code,
|
||||||
|
max_nb_digits: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "source.html")]
|
#[template(path = "source.html")]
|
||||||
struct Source<Code: std::fmt::Display> {
|
struct Source<Code: std::fmt::Display> {
|
||||||
lines: RangeInclusive<usize>,
|
|
||||||
code_html: Code,
|
code_html: Code,
|
||||||
file_path: Option<(String, String)>,
|
file_path: Option<(String, String)>,
|
||||||
|
max_nb_digits: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum SourceContext<'a> {
|
pub(crate) enum SourceContext<'a> {
|
||||||
@ -331,6 +330,15 @@ pub(crate) fn print_src(
|
|||||||
decoration_info: &highlight::DecorationInfo,
|
decoration_info: &highlight::DecorationInfo,
|
||||||
source_context: SourceContext<'_>,
|
source_context: SourceContext<'_>,
|
||||||
) {
|
) {
|
||||||
|
let mut lines = s.lines().count();
|
||||||
|
let line_info = if let SourceContext::Embedded(ref info) = source_context {
|
||||||
|
highlight::LineInfo::new_scraped(lines as u32, info.offset as u32)
|
||||||
|
} else {
|
||||||
|
highlight::LineInfo::new(lines as u32)
|
||||||
|
};
|
||||||
|
if line_info.is_scraped_example {
|
||||||
|
lines += line_info.start_line as usize;
|
||||||
|
}
|
||||||
let code = fmt::from_fn(move |fmt| {
|
let code = fmt::from_fn(move |fmt| {
|
||||||
let current_href = context
|
let current_href = context
|
||||||
.href_from_span(clean::Span::new(file_span), false)
|
.href_from_span(clean::Span::new(file_span), false)
|
||||||
@ -340,13 +348,13 @@ pub(crate) fn print_src(
|
|||||||
s,
|
s,
|
||||||
Some(highlight::HrefContext { context, file_span, root_path, current_href }),
|
Some(highlight::HrefContext { context, file_span, root_path, current_href }),
|
||||||
Some(decoration_info),
|
Some(decoration_info),
|
||||||
|
Some(line_info),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
let lines = s.lines().count();
|
let max_nb_digits = if lines > 0 { lines.ilog(10) + 1 } else { 1 };
|
||||||
match source_context {
|
match source_context {
|
||||||
SourceContext::Standalone { file_path } => Source {
|
SourceContext::Standalone { file_path } => Source {
|
||||||
lines: (1..=lines),
|
|
||||||
code_html: code,
|
code_html: code,
|
||||||
file_path: if let Some(file_name) = file_path.file_name()
|
file_path: if let Some(file_name) = file_path.file_name()
|
||||||
&& let Some(file_path) = file_path.parent()
|
&& let Some(file_path) = file_path.parent()
|
||||||
@ -355,12 +363,14 @@ pub(crate) fn print_src(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
max_nb_digits,
|
||||||
}
|
}
|
||||||
.render_into(&mut writer)
|
.render_into(&mut writer)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
SourceContext::Embedded(info) => {
|
SourceContext::Embedded(info) => {
|
||||||
let lines = (1 + info.offset)..=(lines + info.offset);
|
ScrapedSource { info, code_html: code, max_nb_digits }
|
||||||
ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap();
|
.render_into(&mut writer)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
|
|||||||
--docblock-indent: 24px;
|
--docblock-indent: 24px;
|
||||||
--font-family: "Source Serif 4", NanumBarunGothic, serif;
|
--font-family: "Source Serif 4", NanumBarunGothic, serif;
|
||||||
--font-family-code: "Source Code Pro", monospace;
|
--font-family-code: "Source Code Pro", monospace;
|
||||||
|
--line-number-padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root.sans-serif {
|
:root.sans-serif {
|
||||||
@ -450,9 +451,7 @@ pre.item-decl {
|
|||||||
|
|
||||||
.src .content pre {
|
.src .content pre {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
padding-left: 16px;
|
||||||
.rustdoc.src .example-wrap .src-line-numbers {
|
|
||||||
padding: 20px 0 20px 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -901,29 +900,58 @@ both the code example and the line numbers, so we need to remove the radius in t
|
|||||||
min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
|
min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
-moz-user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding: 14px 8px;
|
padding: 14px 8px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
color: var(--src-line-numbers-span-color);
|
color: var(--src-line-numbers-span-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rustdoc .scraped-example .example-wrap .src-line-numbers {
|
.example-wrap.digits-1 [data-nosnippet] {
|
||||||
padding: 0;
|
width: calc(1ch + var(--line-number-padding) * 2);
|
||||||
}
|
}
|
||||||
.rustdoc .src-line-numbers pre {
|
.example-wrap.digits-2 [data-nosnippet] {
|
||||||
padding: 14px 0;
|
width: calc(2ch + var(--line-number-padding) * 2);
|
||||||
}
|
}
|
||||||
.src-line-numbers a, .src-line-numbers span {
|
.example-wrap.digits-3 [data-nosnippet] {
|
||||||
|
width: calc(3ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-4 [data-nosnippet] {
|
||||||
|
width: calc(4ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-5 [data-nosnippet] {
|
||||||
|
width: calc(5ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-6 [data-nosnippet] {
|
||||||
|
width: calc(6ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-7 [data-nosnippet] {
|
||||||
|
width: calc(7ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-8 [data-nosnippet] {
|
||||||
|
width: calc(8ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
.example-wrap.digits-9 [data-nosnippet] {
|
||||||
|
width: calc(9ch + var(--line-number-padding) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-wrap [data-nosnippet] {
|
||||||
color: var(--src-line-numbers-span-color);
|
color: var(--src-line-numbers-span-color);
|
||||||
padding: 0 8px;
|
text-align: right;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 20px;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
padding: 0 4px;
|
||||||
}
|
}
|
||||||
.src-line-numbers :target {
|
.example-wrap [data-nosnippet]:target {
|
||||||
background-color: transparent;
|
|
||||||
border-right: none;
|
border-right: none;
|
||||||
padding: 0 8px;
|
|
||||||
}
|
}
|
||||||
.src-line-numbers .line-highlighted {
|
.example-wrap .line-highlighted[data-nosnippet] {
|
||||||
background-color: var(--src-line-number-highlighted-background-color);
|
background-color: var(--src-line-number-highlighted-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,7 +1138,7 @@ because of the `[-]` element which would overlap with it. */
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-heading a:hover,
|
.main-heading a:hover,
|
||||||
.example-wrap .rust a:hover,
|
.example-wrap .rust a:hover:not([data-nosnippet]),
|
||||||
.all-items a:hover,
|
.all-items a:hover,
|
||||||
.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
|
.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
|
||||||
.item-table dd a:not(.scrape-help):not(.tooltip):hover,
|
.item-table dd a:not(.scrape-help):not(.tooltip):hover,
|
||||||
@ -1568,7 +1596,7 @@ pre.rust .doccomment {
|
|||||||
color: var(--code-highlight-doc-comment-color);
|
color: var(--code-highlight-doc-comment-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rustdoc.src .example-wrap pre.rust a {
|
.rustdoc.src .example-wrap pre.rust a:not([data-nosnippet]) {
|
||||||
background: var(--codeblock-link-background);
|
background: var(--codeblock-link-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1759,8 +1787,7 @@ instead, we check that it's not a "finger" cursor.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:target {
|
:target:not([data-nosnippet]) {
|
||||||
padding-right: 3px;
|
|
||||||
background-color: var(--target-background-color);
|
background-color: var(--target-background-color);
|
||||||
border-right: 3px solid var(--target-border-color);
|
border-right: 3px solid var(--target-border-color);
|
||||||
}
|
}
|
||||||
@ -3153,7 +3180,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
|||||||
color: #ff7733;
|
color: #ff7733;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme="ayu"] .src-line-numbers .line-highlighted {
|
:root[data-theme="ayu"] a[data-nosnippet].line-highlighted {
|
||||||
color: #708090;
|
color: #708090;
|
||||||
padding-right: 7px;
|
padding-right: 7px;
|
||||||
border-right: 1px solid #ffb44c;
|
border-right: 1px solid #ffb44c;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
// Scroll code block to the given code location
|
// Scroll code block to the given code location
|
||||||
function scrollToLoc(elt, loc, isHidden) {
|
function scrollToLoc(elt, loc, isHidden) {
|
||||||
const lines = elt.querySelector(".src-line-numbers > pre");
|
const lines = elt.querySelectorAll("[data-nosnippet]");
|
||||||
let scrollOffset;
|
let scrollOffset;
|
||||||
|
|
||||||
// If the block is greater than the size of the viewer,
|
// If the block is greater than the size of the viewer,
|
||||||
@ -25,17 +25,17 @@
|
|||||||
const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
|
const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
|
||||||
if (loc[1] - loc[0] > maxLines) {
|
if (loc[1] - loc[0] > maxLines) {
|
||||||
const line = Math.max(0, loc[0] - 1);
|
const line = Math.max(0, loc[0] - 1);
|
||||||
scrollOffset = lines.children[line].offsetTop;
|
scrollOffset = lines[line].offsetTop;
|
||||||
} else {
|
} else {
|
||||||
const halfHeight = elt.offsetHeight / 2;
|
const halfHeight = elt.offsetHeight / 2;
|
||||||
const offsetTop = lines.children[loc[0]].offsetTop;
|
const offsetTop = lines[loc[0]].offsetTop;
|
||||||
const lastLine = lines.children[loc[1]];
|
const lastLine = lines[loc[1]];
|
||||||
const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
|
const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
|
||||||
const offsetMid = (offsetTop + offsetBot) / 2;
|
const offsetMid = (offsetTop + offsetBot) / 2;
|
||||||
scrollOffset = offsetMid - halfHeight;
|
scrollOffset = offsetMid - halfHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.parentElement.scrollTo(0, scrollOffset);
|
lines[0].parentElement.scrollTo(0, scrollOffset);
|
||||||
elt.querySelector(".rust").scrollTo(0, scrollOffset);
|
elt.querySelector(".rust").scrollTo(0, scrollOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,10 +138,8 @@ function highlightSrcLines() {
|
|||||||
if (x) {
|
if (x) {
|
||||||
x.scrollIntoView();
|
x.scrollIntoView();
|
||||||
}
|
}
|
||||||
onEachLazy(document.getElementsByClassName("src-line-numbers"), e => {
|
onEachLazy(document.querySelectorAll("a[data-nosnippet]"), e => {
|
||||||
onEachLazy(e.getElementsByTagName("a"), i_e => {
|
removeClass(e, "line-highlighted");
|
||||||
removeClass(i_e, "line-highlighted");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
for (let i = from; i <= to; ++i) {
|
for (let i = from; i <= to; ++i) {
|
||||||
elem = document.getElementById(i);
|
elem = document.getElementById(i);
|
||||||
@ -200,7 +198,7 @@ const handleSrcHighlight = (function() {
|
|||||||
|
|
||||||
window.addEventListener("hashchange", highlightSrcLines);
|
window.addEventListener("hashchange", highlightSrcLines);
|
||||||
|
|
||||||
onEachLazy(document.getElementsByClassName("src-line-numbers"), el => {
|
onEachLazy(document.querySelectorAll("a[data-nosnippet]"), el => {
|
||||||
el.addEventListener("click", handleSrcHighlight);
|
el.addEventListener("click", handleSrcHighlight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,17 +2,7 @@
|
|||||||
<div class="scraped-example-title">
|
<div class="scraped-example-title">
|
||||||
{{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
|
{{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
<div class="example-wrap">
|
<div class="example-wrap digits-{{max_nb_digits}}"> {# #}
|
||||||
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
|
|
||||||
Do not show "1 2 3 4 5 ..." in web search results. #}
|
|
||||||
<div class="src-line-numbers" data-nosnippet> {# #}
|
|
||||||
<pre>
|
|
||||||
{% for line in lines.clone() %}
|
|
||||||
{# ~#}
|
|
||||||
<span>{{line|safe}}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</pre> {# #}
|
|
||||||
</div> {# #}
|
|
||||||
<pre class="rust"> {# #}
|
<pre class="rust"> {# #}
|
||||||
<code>
|
<code>
|
||||||
{{code_html|safe}}
|
{{code_html|safe}}
|
||||||
|
@ -9,15 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% endmatch %}
|
{% endmatch %}
|
||||||
<div class="example-wrap">
|
<div class="example-wrap digits-{{max_nb_digits}}"> {# #}
|
||||||
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
|
|
||||||
Do not show "1 2 3 4 5 ..." in web search results. #}
|
|
||||||
<div data-nosnippet><pre class="src-line-numbers">
|
|
||||||
{% for line in lines.clone() %}
|
|
||||||
{# ~#}
|
|
||||||
<a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</pre></div> {# #}
|
|
||||||
<pre class="rust"> {# #}
|
<pre class="rust"> {# #}
|
||||||
<code>
|
<code>
|
||||||
{{code_html|safe}}
|
{{code_html|safe}}
|
||||||
|
@ -100,6 +100,7 @@ static TARGETS: &[&str] = &[
|
|||||||
"i586-pc-windows-msvc",
|
"i586-pc-windows-msvc",
|
||||||
"i586-unknown-linux-gnu",
|
"i586-unknown-linux-gnu",
|
||||||
"i586-unknown-linux-musl",
|
"i586-unknown-linux-musl",
|
||||||
|
"i586-unknown-redox",
|
||||||
"i686-apple-darwin",
|
"i686-apple-darwin",
|
||||||
"i686-linux-android",
|
"i686-linux-android",
|
||||||
"i686-pc-windows-gnu",
|
"i686-pc-windows-gnu",
|
||||||
@ -108,7 +109,6 @@ static TARGETS: &[&str] = &[
|
|||||||
"i686-unknown-freebsd",
|
"i686-unknown-freebsd",
|
||||||
"i686-unknown-linux-gnu",
|
"i686-unknown-linux-gnu",
|
||||||
"i686-unknown-linux-musl",
|
"i686-unknown-linux-musl",
|
||||||
"i686-unknown-redox",
|
|
||||||
"i686-unknown-uefi",
|
"i686-unknown-uefi",
|
||||||
"loongarch64-unknown-linux-gnu",
|
"loongarch64-unknown-linux-gnu",
|
||||||
"loongarch64-unknown-linux-musl",
|
"loongarch64-unknown-linux-musl",
|
||||||
|
@ -228,6 +228,9 @@
|
|||||||
//@ revisions: i586_unknown_netbsd
|
//@ revisions: i586_unknown_netbsd
|
||||||
//@ [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd
|
//@ [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd
|
||||||
//@ [i586_unknown_netbsd] needs-llvm-components: x86
|
//@ [i586_unknown_netbsd] needs-llvm-components: x86
|
||||||
|
//@ revisions: i586_unknown_redox
|
||||||
|
//@ [i586_unknown_redox] compile-flags: --target i586-unknown-redox
|
||||||
|
//@ [i586_unknown_redox] needs-llvm-components: x86
|
||||||
//@ revisions: i686_linux_android
|
//@ revisions: i686_linux_android
|
||||||
//@ [i686_linux_android] compile-flags: --target i686-linux-android
|
//@ [i686_linux_android] compile-flags: --target i686-linux-android
|
||||||
//@ [i686_linux_android] needs-llvm-components: x86
|
//@ [i686_linux_android] needs-llvm-components: x86
|
||||||
@ -252,9 +255,6 @@
|
|||||||
//@ revisions: i686_unknown_openbsd
|
//@ revisions: i686_unknown_openbsd
|
||||||
//@ [i686_unknown_openbsd] compile-flags: --target i686-unknown-openbsd
|
//@ [i686_unknown_openbsd] compile-flags: --target i686-unknown-openbsd
|
||||||
//@ [i686_unknown_openbsd] needs-llvm-components: x86
|
//@ [i686_unknown_openbsd] needs-llvm-components: x86
|
||||||
//@ revisions: i686_unknown_redox
|
|
||||||
//@ [i686_unknown_redox] compile-flags: --target i686-unknown-redox
|
|
||||||
//@ [i686_unknown_redox] needs-llvm-components: x86
|
|
||||||
//@ revisions: i686_wrs_vxworks
|
//@ revisions: i686_wrs_vxworks
|
||||||
//@ [i686_wrs_vxworks] compile-flags: --target i686-wrs-vxworks
|
//@ [i686_wrs_vxworks] compile-flags: --target i686-wrs-vxworks
|
||||||
//@ [i686_wrs_vxworks] needs-llvm-components: x86
|
//@ [i686_wrs_vxworks] needs-llvm-components: x86
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
// Small test to ensure the "src-line-numbers" element is only present once on
|
|
||||||
// the page.
|
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
|
||||||
click: "a.src"
|
|
||||||
wait-for: ".src-line-numbers"
|
|
||||||
assert-count: (".src-line-numbers", 1)
|
|
@ -111,28 +111,6 @@ wait-for: "pre.example-line-numbers"
|
|||||||
// Same check with scraped examples line numbers.
|
// Same check with scraped examples line numbers.
|
||||||
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
|
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
|
||||||
|
|
||||||
assert-css: (
|
|
||||||
".scraped-example .src-line-numbers > pre",
|
|
||||||
{
|
|
||||||
// There should not be a radius on the right of the line numbers.
|
|
||||||
"border-top-left-radius": "6px",
|
|
||||||
"border-bottom-left-radius": "6px",
|
|
||||||
"border-top-right-radius": "0px",
|
|
||||||
"border-bottom-right-radius": "0px",
|
|
||||||
},
|
|
||||||
ALL,
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".scraped-example .src-line-numbers",
|
|
||||||
{
|
|
||||||
// There should not be a radius on the right of the line numbers.
|
|
||||||
"border-top-left-radius": "6px",
|
|
||||||
"border-bottom-left-radius": "6px",
|
|
||||||
"border-top-right-radius": "0px",
|
|
||||||
"border-bottom-right-radius": "0px",
|
|
||||||
},
|
|
||||||
ALL,
|
|
||||||
)
|
|
||||||
assert-css: (
|
assert-css: (
|
||||||
".scraped-example .rust",
|
".scraped-example .rust",
|
||||||
{
|
{
|
||||||
@ -149,23 +127,15 @@ define-function: (
|
|||||||
"check-padding",
|
"check-padding",
|
||||||
[path, padding_bottom],
|
[path, padding_bottom],
|
||||||
block {
|
block {
|
||||||
assert-css: (|path| + " .src-line-numbers", {
|
assert-css: (|path| + " span[data-nosnippet]", {
|
||||||
"padding-top": "0px",
|
"padding-top": "0px",
|
||||||
"padding-bottom": "0px",
|
"padding-bottom": "0px",
|
||||||
"padding-left": "0px",
|
"padding-left": "4px",
|
||||||
"padding-right": "0px",
|
"padding-right": "4px",
|
||||||
}, ALL)
|
"margin-right": "20px",
|
||||||
assert-css: (|path| + " .src-line-numbers > pre", {
|
"margin-left": "0px",
|
||||||
"padding-top": "14px",
|
"margin-top": "0px",
|
||||||
"padding-bottom": |padding_bottom|,
|
"margin-bottom": "0px",
|
||||||
"padding-left": "0px",
|
|
||||||
"padding-right": "0px",
|
|
||||||
}, ALL)
|
|
||||||
assert-css: (|path| + " .src-line-numbers > pre > span", {
|
|
||||||
"padding-top": "0px",
|
|
||||||
"padding-bottom": "0px",
|
|
||||||
"padding-left": "8px",
|
|
||||||
"padding-right": "8px",
|
|
||||||
}, ALL)
|
}, ALL)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -196,13 +166,13 @@ define-function: ("check-line-numbers-existence", [], block {
|
|||||||
wait-for-local-storage-false: {"rustdoc-line-numbers": "true" }
|
wait-for-local-storage-false: {"rustdoc-line-numbers": "true" }
|
||||||
assert-false: ".example-line-numbers"
|
assert-false: ".example-line-numbers"
|
||||||
// Line numbers should still be there.
|
// Line numbers should still be there.
|
||||||
assert: ".src-line-numbers"
|
assert-css: ("[data-nosnippet]", { "display": "inline-block"})
|
||||||
// Now disabling the setting.
|
// Now disabling the setting.
|
||||||
click: "input#line-numbers"
|
click: "input#line-numbers"
|
||||||
wait-for-local-storage: {"rustdoc-line-numbers": "true" }
|
wait-for-local-storage: {"rustdoc-line-numbers": "true" }
|
||||||
assert-false: ".example-line-numbers"
|
assert-false: ".example-line-numbers"
|
||||||
// Line numbers should still be there.
|
// Line numbers should still be there.
|
||||||
assert: ".src-line-numbers"
|
assert-css: ("[data-nosnippet]", { "display": "inline-block"})
|
||||||
// Closing settings menu.
|
// Closing settings menu.
|
||||||
click: "#settings-menu"
|
click: "#settings-menu"
|
||||||
wait-for-css: ("#settings", {"display": "none"})
|
wait-for-css: ("#settings", {"display": "none"})
|
||||||
@ -214,18 +184,16 @@ call-function: ("check-line-numbers-existence", {})
|
|||||||
|
|
||||||
// Now checking the line numbers in the source code page.
|
// Now checking the line numbers in the source code page.
|
||||||
click: ".src"
|
click: ".src"
|
||||||
assert-css: (".src-line-numbers", {
|
assert-css: ("a[data-nosnippet]", {
|
||||||
"padding-top": "20px",
|
|
||||||
"padding-bottom": "20px",
|
|
||||||
"padding-left": "4px",
|
|
||||||
"padding-right": "0px",
|
|
||||||
})
|
|
||||||
assert-css: (".src-line-numbers > a", {
|
|
||||||
"padding-top": "0px",
|
"padding-top": "0px",
|
||||||
"padding-bottom": "0px",
|
"padding-bottom": "0px",
|
||||||
"padding-left": "8px",
|
"padding-left": "4px",
|
||||||
"padding-right": "8px",
|
"padding-right": "4px",
|
||||||
})
|
"margin-top": "0px",
|
||||||
|
"margin-bottom": "0px",
|
||||||
|
"margin-left": "0px",
|
||||||
|
"margin-right": "20px",
|
||||||
|
}, ALL)
|
||||||
// Checking that turning off the line numbers setting won't remove line numbers.
|
// Checking that turning off the line numbers setting won't remove line numbers.
|
||||||
call-function: ("check-line-numbers-existence", {})
|
call-function: ("check-line-numbers-existence", {})
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ define-function: (
|
|||||||
block {
|
block {
|
||||||
call-function: ("switch-theme", {"theme": |theme|})
|
call-function: ("switch-theme", {"theme": |theme|})
|
||||||
assert-css: (
|
assert-css: (
|
||||||
"body.src .example-wrap pre.rust a",
|
"body.src .example-wrap pre.rust a:not([data-nosnippet])",
|
||||||
{"background-color": |background_color|},
|
{"background-color": |background_color|},
|
||||||
ALL,
|
ALL,
|
||||||
)
|
)
|
||||||
|
@ -4,52 +4,18 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
|
|||||||
|
|
||||||
// The next/prev buttons vertically scroll the code viewport between examples
|
// The next/prev buttons vertically scroll the code viewport between examples
|
||||||
move-cursor-to: ".scraped-example-list > .scraped-example"
|
move-cursor-to: ".scraped-example-list > .scraped-example"
|
||||||
store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
wait-for: ".scraped-example-list > .scraped-example .next"
|
||||||
"scrollTop": initialScrollTop,
|
store-value: (initialScrollTop, 250)
|
||||||
})
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
||||||
"scrollTop": |initialScrollTop|,
|
"scrollTop": |initialScrollTop|,
|
||||||
})
|
}, NEAR)
|
||||||
focus: ".scraped-example-list > .scraped-example .next"
|
focus: ".scraped-example-list > .scraped-example .next"
|
||||||
press-key: "Enter"
|
press-key: "Enter"
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"scrollTop": |initialScrollTop|
|
|
||||||
}, NEAR)
|
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example .rust", {
|
assert-property-false: (".scraped-example-list > .scraped-example .rust", {
|
||||||
"scrollTop": |initialScrollTop|
|
"scrollTop": |initialScrollTop|
|
||||||
}, NEAR)
|
}, NEAR)
|
||||||
focus: ".scraped-example-list > .scraped-example .prev"
|
focus: ".scraped-example-list > .scraped-example .prev"
|
||||||
press-key: "Enter"
|
press-key: "Enter"
|
||||||
assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"scrollTop": |initialScrollTop|
|
|
||||||
}, NEAR)
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
||||||
"scrollTop": |initialScrollTop|
|
"scrollTop": |initialScrollTop|
|
||||||
}, NEAR)
|
}, NEAR)
|
||||||
|
|
||||||
// The expand button increases the scrollHeight of the minimized code viewport
|
|
||||||
store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight})
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"scrollHeight": |smallOffsetHeight|
|
|
||||||
}, NEAR)
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
|
||||||
"scrollHeight": |smallOffsetHeight|
|
|
||||||
}, NEAR)
|
|
||||||
focus: ".scraped-example-list > .scraped-example .expand"
|
|
||||||
press-key: "Enter"
|
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"offsetHeight": |smallOffsetHeight|
|
|
||||||
}, NEAR)
|
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example .rust", {
|
|
||||||
"offsetHeight": |smallOffsetHeight|
|
|
||||||
}, NEAR)
|
|
||||||
store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"offsetHeight": fullOffsetHeight,
|
|
||||||
})
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .rust", {
|
|
||||||
"offsetHeight": |fullOffsetHeight|,
|
|
||||||
"scrollHeight": |fullOffsetHeight|,
|
|
||||||
})
|
|
||||||
assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
|
|
||||||
"scrollHeight": |fullOffsetHeight|
|
|
||||||
}, NEAR)
|
|
||||||
|
@ -3,35 +3,38 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
|
|||||||
|
|
||||||
set-window-size: (1000, 1000)
|
set-window-size: (1000, 1000)
|
||||||
|
|
||||||
|
// We move the mouse over the scraped example for the prev button to be generated.
|
||||||
|
move-cursor-to: ".scraped-example"
|
||||||
|
|
||||||
// Check that it's not zero.
|
// Check that it's not zero.
|
||||||
assert-property-false: (
|
assert-property-false: (
|
||||||
".more-scraped-examples .scraped-example .src-line-numbers",
|
".more-scraped-examples .scraped-example span[data-nosnippet]",
|
||||||
{"clientWidth": "0"}
|
{"clientWidth": "0"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check that examples with very long lines have the same width as ones that don't.
|
// Check that examples with very long lines have the same width as ones that don't.
|
||||||
store-property: (
|
store-property: (
|
||||||
".more-scraped-examples .scraped-example:nth-child(2) .src-line-numbers",
|
".more-scraped-examples .scraped-example:nth-child(2) span[data-nosnippet]",
|
||||||
{"clientWidth": clientWidth},
|
{"clientWidth": clientWidth},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert-property: (
|
assert-property: (
|
||||||
".more-scraped-examples .scraped-example:nth-child(3) .src-line-numbers",
|
".more-scraped-examples .scraped-example:nth-child(3) span[data-nosnippet]",
|
||||||
{"clientWidth": |clientWidth|}
|
{"clientWidth": |clientWidth|}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert-property: (
|
assert-property: (
|
||||||
".more-scraped-examples .scraped-example:nth-child(4) .src-line-numbers",
|
".more-scraped-examples .scraped-example:nth-child(4) span[data-nosnippet]",
|
||||||
{"clientWidth": |clientWidth|}
|
{"clientWidth": |clientWidth|}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert-property: (
|
assert-property: (
|
||||||
".more-scraped-examples .scraped-example:nth-child(5) .src-line-numbers",
|
".more-scraped-examples .scraped-example:nth-child(5) span[data-nosnippet]",
|
||||||
{"clientWidth": |clientWidth|}
|
{"clientWidth": |clientWidth|}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert-property: (
|
assert-property: (
|
||||||
".more-scraped-examples .scraped-example:nth-child(6) .src-line-numbers",
|
".more-scraped-examples .scraped-example:nth-child(6) span[data-nosnippet]",
|
||||||
{"clientWidth": |clientWidth|}
|
{"clientWidth": |clientWidth|}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,25 +58,6 @@ assert-size: (".more-scraped-examples .scraped-example .example-wrap", {
|
|||||||
"width": |width|,
|
"width": |width|,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check that the expand button works and also that line number aligns with code.
|
|
||||||
move-cursor-to: ".scraped-example .rust"
|
|
||||||
click: ".scraped-example .button-holder .expand"
|
|
||||||
wait-for: ".scraped-example.expanded"
|
|
||||||
// They should have the same y position.
|
|
||||||
compare-elements-position: (
|
|
||||||
".scraped-example.expanded .src-line-numbers pre span",
|
|
||||||
".scraped-example.expanded .rust code",
|
|
||||||
["y"],
|
|
||||||
)
|
|
||||||
// And they should have the same height.
|
|
||||||
compare-elements-size: (
|
|
||||||
".scraped-example.expanded .src-line-numbers",
|
|
||||||
".scraped-example.expanded .rust",
|
|
||||||
["height"],
|
|
||||||
)
|
|
||||||
// Collapse code again.
|
|
||||||
click: ".scraped-example .button-holder .expand"
|
|
||||||
|
|
||||||
// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed
|
// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed
|
||||||
// correctly.
|
// correctly.
|
||||||
|
|
||||||
@ -98,7 +82,7 @@ define-function: (
|
|||||||
[],
|
[],
|
||||||
block {
|
block {
|
||||||
// Title should be above the code.
|
// Title should be above the code.
|
||||||
store-position: (".scraped-example .example-wrap .src-line-numbers", {"x": x, "y": y})
|
store-position: (".scraped-example .example-wrap", {"x": x, "y": y})
|
||||||
store-size: (".scraped-example .scraped-example-title", { "height": title_height })
|
store-size: (".scraped-example .scraped-example-title", { "height": title_height })
|
||||||
|
|
||||||
assert-position: (".scraped-example .scraped-example-title", {
|
assert-position: (".scraped-example .scraped-example-title", {
|
||||||
@ -107,10 +91,13 @@ define-function: (
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Line numbers should be right beside the code.
|
// Line numbers should be right beside the code.
|
||||||
compare-elements-position: (
|
compare-elements-position-near: (
|
||||||
".scraped-example .example-wrap .src-line-numbers",
|
".scraped-example .example-wrap span[data-nosnippet]",
|
||||||
".scraped-example .example-wrap .rust",
|
// On the first line, the code starts with `fn main` so we have a keyword.
|
||||||
["y"],
|
".scraped-example .example-wrap .rust span.kw",
|
||||||
|
// They're not exactly the same size but since they're on the same line,
|
||||||
|
// it's kinda the same.
|
||||||
|
{"y": 2},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -8,13 +8,13 @@ set-window-size: (600, 800)
|
|||||||
assert-property: ("html", {"scrollTop": "0"})
|
assert-property: ("html", {"scrollTop": "0"})
|
||||||
|
|
||||||
click: '//a[text() = "barbar" and @href="#5-7"]'
|
click: '//a[text() = "barbar" and @href="#5-7"]'
|
||||||
assert-property: ("html", {"scrollTop": "208"})
|
assert-property: ("html", {"scrollTop": "206"})
|
||||||
click: '//a[text() = "bar" and @href="#28-36"]'
|
click: '//a[text() = "bar" and @href="#28-36"]'
|
||||||
assert-property: ("html", {"scrollTop": "239"})
|
assert-property: ("html", {"scrollTop": "239"})
|
||||||
click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]'
|
click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]'
|
||||||
assert-property: ("html", {"scrollTop": "136"})
|
assert-property: ("html", {"scrollTop": "134"})
|
||||||
|
|
||||||
// We now check that clicking on lines doesn't change the scroll
|
// We now check that clicking on lines doesn't change the scroll
|
||||||
// Extra information: the "sub_fn" function header is on line 1.
|
// Extra information: the "sub_fn" function header is on line 1.
|
||||||
click: '//*[@id="6"]'
|
click: '//*[@id="6"]'
|
||||||
assert-property: ("html", {"scrollTop": "136"})
|
assert-property: ("html", {"scrollTop": "134"})
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||||
set-window-size: (800, 1000)
|
set-window-size: (800, 1000)
|
||||||
// "scrollWidth" should be superior than "clientWidth".
|
// "scrollWidth" should be superior than "clientWidth".
|
||||||
assert-property: ("body", {"scrollWidth": 1776, "clientWidth": 800})
|
assert-property: ("body", {"scrollWidth": 1780, "clientWidth": 800})
|
||||||
|
|
||||||
// Both properties should be equal (ie, no scroll on the code block).
|
// Both properties should be equal (ie, no scroll on the code block).
|
||||||
assert-property: (".example-wrap .rust", {"scrollWidth": 1662, "clientWidth": 1662})
|
assert-property: (".example-wrap .rust", {"scrollWidth": 1715, "clientWidth": 1715})
|
||||||
|
@ -3,7 +3,7 @@ include: "utils.goml"
|
|||||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||||
show-text: true
|
show-text: true
|
||||||
// Check that we can click on the line number.
|
// Check that we can click on the line number.
|
||||||
click: ".src-line-numbers > a:nth-child(4)" // This is the anchor for line 4.
|
click: "//a[@data-nosnippet and text()='4']" // This is the anchor for line 4.
|
||||||
// Ensure that the page URL was updated.
|
// Ensure that the page URL was updated.
|
||||||
assert-document-property: ({"URL": "lib.rs.html#4"}, ENDS_WITH)
|
assert-document-property: ({"URL": "lib.rs.html#4"}, ENDS_WITH)
|
||||||
assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
|
assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
|
||||||
@ -14,11 +14,11 @@ assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
|
|||||||
assert-css: ("//*[@id='4']", {"border-right-width": "0px"})
|
assert-css: ("//*[@id='4']", {"border-right-width": "0px"})
|
||||||
// We now check that the good anchors are highlighted
|
// We now check that the good anchors are highlighted
|
||||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4-6"
|
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4-6"
|
||||||
assert-attribute-false: (".src-line-numbers > a:nth-child(3)", {"class": "line-highlighted"})
|
assert-attribute-false: ("//a[@data-nosnippet and text()='3']", {"class": "line-highlighted"})
|
||||||
assert-attribute: (".src-line-numbers > a:nth-child(4)", {"class": "line-highlighted"})
|
assert-attribute: ("//a[@data-nosnippet and text()='4']", {"class": "line-highlighted"})
|
||||||
assert-attribute: (".src-line-numbers > a:nth-child(5)", {"class": "line-highlighted"})
|
assert-attribute: ("//a[@data-nosnippet and text()='5']", {"class": "line-highlighted"})
|
||||||
assert-attribute: (".src-line-numbers > a:nth-child(6)", {"class": "line-highlighted"})
|
assert-attribute: ("//a[@data-nosnippet and text()='6']", {"class": "line-highlighted"})
|
||||||
assert-attribute-false: (".src-line-numbers > a:nth-child(7)", {"class": "line-highlighted"})
|
assert-attribute-false: ("//a[@data-nosnippet and text()='7']", {"class": "line-highlighted"})
|
||||||
|
|
||||||
define-function: (
|
define-function: (
|
||||||
"check-colors",
|
"check-colors",
|
||||||
@ -26,12 +26,12 @@ define-function: (
|
|||||||
block {
|
block {
|
||||||
call-function: ("switch-theme", {"theme": |theme|})
|
call-function: ("switch-theme", {"theme": |theme|})
|
||||||
assert-css: (
|
assert-css: (
|
||||||
".src-line-numbers > a:not(.line-highlighted)",
|
"a[data-nosnippet]:not(.line-highlighted)",
|
||||||
{"color": |color|, "background-color": |background_color|},
|
{"color": |color|, "background-color": |background_color|},
|
||||||
ALL,
|
ALL,
|
||||||
)
|
)
|
||||||
assert-css: (
|
assert-css: (
|
||||||
".src-line-numbers > a.line-highlighted",
|
"a[data-nosnippet].line-highlighted",
|
||||||
{"color": |highlight_color|, "background-color": |highlight_background_color|},
|
{"color": |highlight_color|, "background-color": |highlight_background_color|},
|
||||||
ALL,
|
ALL,
|
||||||
)
|
)
|
||||||
@ -61,37 +61,37 @@ call-function: ("check-colors", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// This is to ensure that the content is correctly align with the line numbers.
|
// This is to ensure that the content is correctly align with the line numbers.
|
||||||
compare-elements-position: ("//*[@id='1']", ".rust > code > span", ["y"])
|
compare-elements-position-near: ("//*[@id='1']", ".rust > code > span", {"y": 2})
|
||||||
// Check the `href` property so that users can treat anchors as links.
|
// Check the `href` property so that users can treat anchors as links.
|
||||||
assert-property: (".src-line-numbers > a:nth-child(1)", {
|
assert-property: ("//a[@data-nosnippet and text()='1']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#1"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#1"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
assert-property: (".src-line-numbers > a:nth-child(2)", {
|
assert-property: ("//a[@data-nosnippet and text()='2']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#2"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#2"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
assert-property: (".src-line-numbers > a:nth-child(3)", {
|
assert-property: ("//a[@data-nosnippet and text()='3']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#3"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#3"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
assert-property: (".src-line-numbers > a:nth-child(4)", {
|
assert-property: ("//a[@data-nosnippet and text()='4']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#4"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#4"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
assert-property: (".src-line-numbers > a:nth-child(5)", {
|
assert-property: ("//a[@data-nosnippet and text()='5']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#5"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#5"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
assert-property: (".src-line-numbers > a:nth-child(6)", {
|
assert-property: ("//a[@data-nosnippet and text()='6']", {
|
||||||
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#6"
|
"href": |DOC_PATH| + "/src/test_docs/lib.rs.html#6"
|
||||||
}, ENDS_WITH)
|
}, ENDS_WITH)
|
||||||
|
|
||||||
// Assert that the line numbers text is aligned to the right.
|
// Assert that the line numbers text is aligned to the right.
|
||||||
assert-css: (".src-line-numbers", {"text-align": "right"})
|
assert-css: ("a[data-nosnippet]", {"text-align": "right"}, ALL)
|
||||||
|
|
||||||
// Now let's check that clicking on something else than the line number doesn't
|
// Now let's check that clicking on something else than the line number doesn't
|
||||||
// do anything (and certainly not add a `#NaN` to the URL!).
|
// do anything (and certainly not add a `#NaN` to the URL!).
|
||||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||||
// We use this assert-position to know where we will click.
|
// We use this assert-position to know where we will click.
|
||||||
assert-position: ("//*[@id='1']", {"x": 88, "y": 171})
|
assert-position: ("//*[@id='1']", {"x": 81, "y": 169})
|
||||||
// We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
|
// We click on the left of the "1" anchor but still in the `a[data-nosnippet]`.
|
||||||
click: (163, 77)
|
click: (77, 163)
|
||||||
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
|
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
|
||||||
|
|
||||||
// Checking the source code sidebar.
|
// Checking the source code sidebar.
|
||||||
|
@ -31,7 +31,8 @@ fn babar() {}
|
|||||||
//@ has - '//pre[@class="rust"]//a/@href' '/struct.String.html'
|
//@ has - '//pre[@class="rust"]//a/@href' '/struct.String.html'
|
||||||
//@ has - '//pre[@class="rust"]//a/@href' '/primitive.u32.html'
|
//@ has - '//pre[@class="rust"]//a/@href' '/primitive.u32.html'
|
||||||
//@ has - '//pre[@class="rust"]//a/@href' '/primitive.str.html'
|
//@ has - '//pre[@class="rust"]//a/@href' '/primitive.str.html'
|
||||||
//@ count - '//pre[@class="rust"]//a[@href="#23"]' 5
|
// The 5 links to line 23 and the line 23 itself.
|
||||||
|
//@ count - '//pre[@class="rust"]//a[@href="#23"]' 6
|
||||||
//@ has - '//pre[@class="rust"]//a[@href="../../source_code/struct.SourceCode.html"]' \
|
//@ has - '//pre[@class="rust"]//a[@href="../../source_code/struct.SourceCode.html"]' \
|
||||||
// 'source_code::SourceCode'
|
// 'source_code::SourceCode'
|
||||||
pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
|
pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
|
||||||
@ -50,8 +51,8 @@ pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {}
|
|||||||
pub trait AnotherTrait {}
|
pub trait AnotherTrait {}
|
||||||
pub trait WhyNot {}
|
pub trait WhyNot {}
|
||||||
|
|
||||||
//@ has - '//pre[@class="rust"]//a[@href="#50"]' 'AnotherTrait'
|
//@ has - '//pre[@class="rust"]//a[@href="#51"]' 'AnotherTrait'
|
||||||
//@ has - '//pre[@class="rust"]//a[@href="#51"]' 'WhyNot'
|
//@ has - '//pre[@class="rust"]//a[@href="#52"]' 'WhyNot'
|
||||||
pub fn foo3<T, V>(t: &T, v: &V)
|
pub fn foo3<T, V>(t: &T, v: &V)
|
||||||
where
|
where
|
||||||
T: AnotherTrait,
|
T: AnotherTrait,
|
||||||
@ -60,7 +61,7 @@ where
|
|||||||
|
|
||||||
pub trait AnotherTrait2 {}
|
pub trait AnotherTrait2 {}
|
||||||
|
|
||||||
//@ has - '//pre[@class="rust"]//a[@href="#61"]' 'AnotherTrait2'
|
//@ has - '//pre[@class="rust"]//a[@href="#62"]' 'AnotherTrait2'
|
||||||
pub fn foo4() {
|
pub fn foo4() {
|
||||||
let x: Vec<&dyn AnotherTrait2> = Vec::new();
|
let x: Vec<&dyn AnotherTrait2> = Vec::new();
|
||||||
}
|
}
|
||||||
|
35
tests/rustdoc/source-line-numbers.rs
Normal file
35
tests/rustdoc/source-line-numbers.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// This test ensures that we have the expected number of line generated.
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
//@ has 'src/foo/source-line-numbers.rs.html'
|
||||||
|
//@ count - '//a[@data-nosnippet]' 35
|
||||||
|
//@ has - '//a[@id="35"]' '35'
|
||||||
|
|
||||||
|
#[
|
||||||
|
macro_export
|
||||||
|
]
|
||||||
|
macro_rules! bar {
|
||||||
|
($x:ident) => {{
|
||||||
|
$x += 2;
|
||||||
|
$x *= 2;
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
multi line
|
||||||
|
comment
|
||||||
|
*/
|
||||||
|
fn x(_: u8, _: u8) {}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
let mut y = 0;
|
||||||
|
bar!(y);
|
||||||
|
println!("
|
||||||
|
{y}
|
||||||
|
");
|
||||||
|
x(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
}
|
@ -2,7 +2,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/suggest-libname-only-1.rs:7:1
|
--> $DIR/suggest-libname-only-1.rs:7:1
|
||||||
|
|
|
|
||||||
LL | extern { }
|
LL | extern { }
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: `#[warn(missing_abi)]` on by default
|
= note: `#[warn(missing_abi)]` on by default
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/suggest-libname-only-2.rs:7:1
|
--> $DIR/suggest-libname-only-2.rs:7:1
|
||||||
|
|
|
|
||||||
LL | extern { }
|
LL | extern { }
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: `#[warn(missing_abi)]` on by default
|
= note: `#[warn(missing_abi)]` on by default
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ error: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/cli-lint-override.rs:12:1
|
--> $DIR/cli-lint-override.rs:12:1
|
||||||
|
|
|
|
||||||
LL | extern fn foo() {}
|
LL | extern fn foo() {}
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: requested on the command line with `-F missing-abi`
|
= note: requested on the command line with `-F missing-abi`
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/cli-lint-override.rs:12:1
|
--> $DIR/cli-lint-override.rs:12:1
|
||||||
|
|
|
|
||||||
LL | extern fn foo() {}
|
LL | extern fn foo() {}
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: requested on the command line with `--force-warn missing-abi`
|
= note: requested on the command line with `--force-warn missing-abi`
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ error: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/cli-lint-override.rs:12:1
|
--> $DIR/cli-lint-override.rs:12:1
|
||||||
|
|
|
|
||||||
LL | extern fn foo() {}
|
LL | extern fn foo() {}
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: requested on the command line with `-D missing-abi`
|
= note: requested on the command line with `-D missing-abi`
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/bad-lit-suffixes.rs:3:1
|
--> $DIR/bad-lit-suffixes.rs:3:1
|
||||||
|
|
|
|
||||||
LL | extern
|
LL | extern
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: `#[warn(missing_abi)]` on by default
|
= note: `#[warn(missing_abi)]` on by default
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/bad-lit-suffixes.rs:7:1
|
--> $DIR/bad-lit-suffixes.rs:7:1
|
||||||
|
|
|
|
||||||
LL | extern
|
LL | extern
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
||||||
error: suffixes on string literals are invalid
|
error: suffixes on string literals are invalid
|
||||||
--> $DIR/bad-lit-suffixes.rs:12:5
|
--> $DIR/bad-lit-suffixes.rs:12:5
|
||||||
|
@ -8,7 +8,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/lit-err-in-macro.rs:3:9
|
--> $DIR/lit-err-in-macro.rs:3:9
|
||||||
|
|
|
|
||||||
LL | extern $abi fn f() {}
|
LL | extern $abi fn f() {}
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
...
|
...
|
||||||
LL | f!("Foo"__);
|
LL | f!("Foo"__);
|
||||||
| ----------- in this macro invocation
|
| ----------- in this macro invocation
|
||||||
|
@ -26,7 +26,7 @@ warning: extern declarations without an explicit ABI are deprecated
|
|||||||
--> $DIR/inner-attrs.rs:82:1
|
--> $DIR/inner-attrs.rs:82:1
|
||||||
|
|
|
|
||||||
LL | extern {
|
LL | extern {
|
||||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
||||||
|
|
|
|
||||||
= note: `#[warn(missing_abi)]` on by default
|
= note: `#[warn(missing_abi)]` on by default
|
||||||
|
|
||||||
|
@ -285,6 +285,13 @@ LL | Enum::<()>::TSVariant::<()>(());
|
|||||||
| --------- ^^ type argument not allowed
|
| --------- ^^ type argument not allowed
|
||||||
| |
|
| |
|
||||||
| not allowed on tuple variant `TSVariant`
|
| not allowed on tuple variant `TSVariant`
|
||||||
|
|
|
||||||
|
= note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
|
||||||
|
help: remove the generics arguments from one of the path segments
|
||||||
|
|
|
||||||
|
LL - Enum::<()>::TSVariant::<()>(());
|
||||||
|
LL + Enum::<()>::TSVariant(());
|
||||||
|
|
|
||||||
|
|
||||||
error[E0109]: type arguments are not allowed on this type
|
error[E0109]: type arguments are not allowed on this type
|
||||||
--> $DIR/enum-variant-generic-args.rs:57:24
|
--> $DIR/enum-variant-generic-args.rs:57:24
|
||||||
@ -354,7 +361,12 @@ LL | Enum::<()>::SVariant::<()> { v: () };
|
|||||||
| |
|
| |
|
||||||
| not allowed on variant `SVariant`
|
| not allowed on variant `SVariant`
|
||||||
|
|
|
|
||||||
= note: enum variants can't have type parameters
|
= note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
|
||||||
|
help: remove the generics arguments from one of the path segments
|
||||||
|
|
|
||||||
|
LL - Enum::<()>::SVariant::<()> { v: () };
|
||||||
|
LL + Enum::<()>::SVariant { v: () };
|
||||||
|
|
|
||||||
|
|
||||||
error[E0109]: type arguments are not allowed on this type
|
error[E0109]: type arguments are not allowed on this type
|
||||||
--> $DIR/enum-variant-generic-args.rs:75:23
|
--> $DIR/enum-variant-generic-args.rs:75:23
|
||||||
@ -451,6 +463,13 @@ LL | Enum::<()>::UVariant::<()>;
|
|||||||
| -------- ^^ type argument not allowed
|
| -------- ^^ type argument not allowed
|
||||||
| |
|
| |
|
||||||
| not allowed on unit variant `UVariant`
|
| not allowed on unit variant `UVariant`
|
||||||
|
|
|
||||||
|
= note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
|
||||||
|
help: remove the generics arguments from one of the path segments
|
||||||
|
|
|
||||||
|
LL - Enum::<()>::UVariant::<()>;
|
||||||
|
LL + Enum::<()>::UVariant;
|
||||||
|
|
|
||||||
|
|
||||||
error[E0109]: type arguments are not allowed on this type
|
error[E0109]: type arguments are not allowed on this type
|
||||||
--> $DIR/enum-variant-generic-args.rs:93:23
|
--> $DIR/enum-variant-generic-args.rs:93:23
|
||||||
|
@ -1043,7 +1043,6 @@ users_on_vacation = [
|
|||||||
"jyn514",
|
"jyn514",
|
||||||
"nnethercote",
|
"nnethercote",
|
||||||
"workingjubilee",
|
"workingjubilee",
|
||||||
"kobzol",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[assign.warn_non_default_branch.exceptions]]
|
[[assign.warn_non_default_branch.exceptions]]
|
||||||
|
Loading…
Reference in New Issue
Block a user